NTT注意事项

匿名 (未验证) 提交于 2019-12-03 00:38:01

记住几个常用的素数及原根:

998244353==>3

1004535809==>3

167772161==>3

参考这里:

https://www.cnblogs.com/Guess2/p/8422205.html

贴代码,看细节:

#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn=3e6+10; const long long mod=1004535809;//注意模数  int n,m; long long a[maxn],b[maxn];  inline long long Pow(long long x,long long b) { 	long long res=1; 	for(;b;b>>=1) 	{ 		if(b&1) res=res*x%mod; 		x=x*x%mod;		 	} 	return res; }  namespace TNT { 	long long p[maxn],w[21]; 	int n,m; 	inline void init(int len) 	{ 		for(n=1,m=0;n<=len;n<<=1,m++);//注意是n<=len等于号不能丢  		for(int i=1;i<n;i++) p[i]=(p[i>>1]>>1)|((i&1)<<(m-1)); 	} 	inline void ntt(long long a[],int flag) 	{ 		for(int i=1;i<n;i++) if(i<p[i]) swap(a[i],a[p[i]]); 		w[0]=Pow(3*1ll,(mod-1)/n); 		if(flag) w[0]=Pow(w[0],mod-2); 		for(int i=1;i<m;i++) w[i]=w[i-1]*w[i-1]%mod; 		for(int i=1,x=m-1;i<n;x--,i<<=1)//后面这些全部不能加=  			for(int j=0;j<n;j+=i<<1)//同上  			{ 				long long wi=1; 				for(int k=0;k<i;k++,wi=wi*w[x]%mod) 				{ 					long long xx=a[j+k]; 					long long yy=a[i+k+j]*wi%mod; 					a[j+k]=(xx+yy)%mod;//注意是j+k  					a[j+k+i]=(xx-yy+mod)%mod; 				} 			} 		if(flag) 		{ 			long long inv=Pow(n,mod-2); 			for(int i=0;i<n;i++) a[i]=a[i]*inv%mod; 		} 	} }  int main() { 	scanf("%d%d",&n,&m); 	for(int i=0;i<=n;i++) scanf("%lld",&a[i]); 	for(int i=0;i<=m;i++) scanf("%lld",&b[i]); 	m+=n; 	TNT::init(m); 	TNT::ntt(a,0),TNT::ntt(b,0); 	for(int i=0;i<TNT::n;i++) a[i]=a[i]*b[i]%mod;//注意这里是TNT::n  	TNT::ntt(a,1); 	for(int i=0;i<=m;i++) printf("%lld ",a[i]); 	return 0; } 

  

原文:https://www.cnblogs.com/linda-fcj/p/9241319.html

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!