NTT注意事项
Posted linda-fcj
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NTT注意事项相关的知识,希望对你有一定的参考价值。
记住几个常用的素数及原根:
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; }
以上是关于NTT注意事项的主要内容,如果未能解决你的问题,请参考以下文章