FFT【快速傅里叶变换】:
/* I will wait for you */ #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<ctime> #include<algorithm> #include<iostream> #include<fstream> #include<vector> #include<queue> #include<deque> #include<set> #include<map> #include<string> #define make make_pair #define fi first #define se second using namespace std; typedef long long LL; typedef unsigned long long ULL; typedef pair<int,int> PII; const int maxn=200010; const int maxm=1010; const int maxs=26; const int INF=1<<29; const int P=1000000007; const double error=1e-9; const double Pi=3.14159265358979323846; struct complex { double re,im; complex(double x=0.0,double y=0.0) { re=x;im=y; } complex operator + (complex a) { return complex(re+a.re,im+a.im); } complex operator - (complex a) { return complex(re-a.re,im-a.im); } complex operator * (complex a) { return complex(re*a.re-im*a.im,re*a.im+im*a.re); } }a[maxn],b[maxn],w[2][maxn]; int n,m,rev[maxn];char ca[maxn],cb[maxn]; void fft(complex* a,int f) { for(int i=0;i<n;i++) if(rev[i]>i) swap(a[i],a[rev[i]]); complex x,y; for(int i=1;i<n;i<<=1) for(int j=0,l=n/(i<<1);j<n;j+=(i<<1)) for(int k=0,t=0;k<i;k++,t+=l) x=a[j+k],y=w[f][t]*a[i+j+k],a[j+k]=x+y,a[i+j+k]=x-y; if(f) for(int i=0;i<n;i++) a[i].re/=n; } void work() { memset(rev,0,sizeof(rev)); for(int i=0;i<n;i++) for(int j=1,x=i;j<n;j<<=1,x>>=1) (rev[i]<<=1)|=(x&1); for(int i=0;i<n;i++) w[0][i]=w[1][i]=complex(cos(2*Pi*i/n),sin(2*Pi*i/n)),w[1][i].im=-w[1][i].im; } void read() { scanf("%d",&m);scanf("%s%s",ca,cb); for(int i=0;i<m;i++) a[i].re=ca[i]-'0'; for(int i=0;i<m;i++) b[i].re=cb[i]-'0'; for(n=1;n<(m<<1);n<<=1); } void write() { for(int i=m*2-2,c=0,t;i>=0;i--) t=a[i].re+c+0.1,a[i].re=i?t%10:t,c=t/10; for(int i=0;i<2*m-1;i++) printf("%g",a[i].re);putchar(10); } int main() { read();work();fft(a,0);fft(b,0); for(int i=0;i<n;i++) a[i]=a[i]*b[i]; fft(a,1);write(); return 0; }NTT【数论变换】:
/* I will wait for you */ #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<ctime> #include<algorithm> #include<iostream> #include<fstream> #include<vector> #include<queue> #include<deque> #include<set> #include<map> #include<string> #define make make_pair #define fi first #define se second using namespace std; typedef long long LL; typedef unsigned long long ULL; typedef pair<int,int> PII; const int maxn=200010; const int maxm=1010; const int maxs=26; const int INF=1<<29; const int P=479<<21^1; const int G=3; const double error=1e-9; LL a[maxn],b[maxn],w[2][maxn],tem[maxn]; int n,m,s[2],rev[maxn];char ca[maxn],cb[maxn]; LL qpow(LL a,LL b) { LL ans=1; for(;b;a=a*a%P,b>>=1) if(b&1) ans=ans*a%P; return ans; } void ntt(LL *a,int f) { for(int i=0;i<n;i++) if(rev[i]>i) swap(a[i],a[rev[i]]); LL x,y,c=qpow(n,P-2); for(int i=1;i<n;i<<=1) for(int j=0,l=n/(i<<1);j<n;j+=(i<<1)) for(int k=0,t=0;k<i;k++,t+=l) x=a[j+k],y=w[f][t]*a[i+j+k]%P,a[j+k]=(x+y)%P,a[i+j+k]=(x-y+P)%P; if(f) for(int i=0;i<n;i++) (a[i]*=c)%=P; } void work() { memset(rev,0,sizeof(rev)); s[0]=qpow(G,(P-1)/n);s[1]=qpow(s[0],P-2); for(int i=0;i<n;i++) for(int j=1,x=i;j<n;j<<=1,x>>=1) (rev[i]<<=1)|=(x&1); for(int i=0;i<n;i++) for(int j=0;j<2;j++) w[j][i]=i?w[j][i-1]*s[j]%P:1; } void read() { scanf("%d",&m);scanf("%s%s",ca,cb); for(int i=0;i<m;i++) a[i]=ca[i]-'0'; for(int i=0;i<m;i++) b[i]=cb[i]-'0'; for(n=1;n<(m<<1);n<<=1); } void write() { for(int i=m*2-2,c=0,t;i>=0;i--) t=a[i]+c,a[i]=i?t%10:t,c=t/10; for(int i=0;i<2*m-1;i++) printf("%d",a[i]);putchar(10); } int main() { read();work();ntt(a,0);ntt(b,0); for(int i=0;i<n;i++) (a[i]*=b[i])%=P; ntt(a,1);write(); return 0; }
理论上NTT的速度要比FFT快.但是我写的反而要慢不少.不明觉厉.