FFT

  1 #include<cstdio> 
  2 #include<cstring>
  3 #include<cmath>
  4 #include<ctime>
  5 #include<iostream>
  6 #include<algorithm>
  7 #include<queue>
  8 #include<stack>
  9 #include<set>
 10 #define esp (1e-8)
 11 #define maxint (2147483647)
 12 #define pi (3.141592653589793)
 13 #define l(a) ((a)<<1)
 14 #define r(a) ((a)<<1|1)
 15 #define b(a) (1<<(a))
 16 #define rep(i,a,b) for(int i=a;i<=(b);i++)
 17 #define clr(a) memset(a,0,sizeof(a))
 18 typedef long long ll;
 19 using namespace std;
 20 int readint(){
 21     int t=0,f=1;char c=getchar();
 22     while(!isdigit(c)){
 23         if(c=='-') f=-1;
 24         c=getchar();
 25     }
 26     while(isdigit(c)){
 27         t=(t<<3)+(t<<1)+c-'0';
 28         c=getchar();
 29     }
 30     return t*f;
 31 }
 32 ll readll(){
 33     ll t=0ll,f=1ll;char c=getchar();
 34     while(!isdigit(c)){
 35         if(c=='-') f=-1ll;
 36         c=getchar();
 37     }
 38     while(isdigit(c)){
 39         t=(t<<3ll)+(t<<1ll)+ll(c-'0');
 40         c=getchar();
 41     }
 42     return t*f;
 43 }
 44 const int maxk=100,maxn=500009;
 45 int n,m,cnt=0;
 46 struct complex{
 47     double r,i;
 48     inline complex(double R,double I){
 49         r=R;i=I;
 50     }
 51     inline complex(){}
 52     inline void out(){
 53         if(abs(i)>esp) printf("%.2lf %.2lfi
",r,i);
 54         else printf("%.2lf
",r);
 55     }
 56     inline complex operator +(const complex A)const{
 57         return complex(r+A.r,i+A.i);
 58     }
 59     inline complex operator -(const complex A)const{
 60         return complex(r-A.r,i-A.i);
 61     }
 62     inline complex operator *(const complex A)const{
 63         return complex(r*A.r-i*A.i,i*A.r+r*A.i);
 64     }
 65 }pool[maxk][maxn],*S[maxk];
 66 complex*newarray(){
 67     return S[--cnt];
 68 }
 69 int rev(int t){//将t化为2^k 
 70     int T=0;
 71     for(T=0;b(T)<t;T++);
 72     return b(T);
 73 }
 74 complex*FFT(complex a[],int t,int opt){//t为2的整数次幂 opt==1->FFT opt==-1->逆FFT
 75     if(t==1) return a;
 76     complex w=complex(1,0),w1=complex(cos(2*pi/t),sin(2*pi/t*opt));//只需在sin中乘上opt 
 77     complex*y=newarray(),*a0=newarray(),*a1=newarray();
 78     rep(i,0,t-1){//奇偶分组 
 79         if(i&1) a1[i>>1]=a[i];
 80         else a0[i>>1]=a[i];
 81     }
 82     complex*y0=FFT(a0,t>>1,opt),*y1=FFT(a1,t>>1,opt);//递归
 83     rep(i,0,(t>>1)-1){//利用t>>1的情况计算n的情况,注意公式的推导:A(x)=A0(x^2)+xA1(x^2) 
 84         y[i]=y0[i]+w*y1[i];
 85         y[i+(t>>1)]=y0[i]-w*y1[i];
 86         w=w*w1;
 87     }
 88     S[cnt++]=a0;S[cnt++]=a1;if(y0!=a0) S[cnt++]=y0;if(y1!=a1) S[cnt++]=y1;
 89     return y;
 90 }
 91 complex*DFT(complex a[],int t,int opt){//t为2的整数次幂 opt==1->FFT opt==-1->逆FFT
 92     t=rev(t);
 93     complex*ans=FFT(a,t,opt);
 94     if(opt==-1) rep(i,0,t-1){
 95         (ans+i)->r/=t;(ans+i)->i/=t;
 96     }
 97     return ans;
 98 }
 99 void init(){
100     rep(i,0,maxk-1) S[cnt++]=pool[i];
101 }
102 int main(){
103     //freopen("#intput.txt","r",stdin);
104     //freopen("#output.txt","w",stdout);
105     init();
106     n=readint();m=readint();n++;m++;
107     complex*a=newarray(),*b=newarray();
108     rep(i,0,n-1) a[i].r=readint();
109     rep(i,0,m-1) b[i].r=readint();
110     int N=max(n,m);N=rev(N)<<1;
111     complex*A=DFT(a,N,1),*B=DFT(b,N,1),*Ans;
112     rep(i,0,N-1) A[i]=A[i]*B[i];
113     Ans=DFT(A,N,-1);N--;
114     rep(i,0,n+m-2){
115         printf("%.0lf",(Ans+i)->r+esp);
116         putchar(i==N?'
':' ');
117     }
118     //fclose(stdin);
119     //fclose(stdout);
120     return 0;
121 }
多项式乘法 手写栈 时空nlogn
  1 #include<cstdio> 
  2 #include<cstring>
  3 #include<cmath>
  4 #include<ctime>
  5 #include<iostream>
  6 #include<algorithm>
  7 #include<queue>
  8 #include<set>
  9 #define pi (3.14159265358979323846)
 10 #define maxint (2147483647)
 11 #define l(a) ((a)<<1)
 12 #define r(a) ((a)<<1|1)
 13 #define b(a) (1<<(a))
 14 #define esp (1e-4)
 15 #define rep(i,a,b) for(int i=a;i<=(b);i++)
 16 #define clr(a) memset(a,0,sizeof(a))
 17 typedef long long ll;
 18 using namespace std;
 19 int readint(){
 20     int t=0,f=1;char c=getchar();
 21     while(!isdigit(c)){
 22         if(c=='-') f=-1;
 23         c=getchar();
 24     }
 25     while(isdigit(c)){
 26         t=(t<<3)+(t<<1)+c-'0';
 27         c=getchar();
 28     }
 29     return t*f;
 30 }
 31 void readstr(char s[]){
 32     int p=0;char c=getchar();
 33     while(!isdigit(c)) c=getchar();
 34     while(isdigit(c)){
 35         s[p++]=c;c=getchar();
 36     }
 37 }
 38 const int maxn=250000;
 39 struct complex{
 40     double r,i;
 41     inline complex(double R,double I){
 42         r=R;i=I;
 43     }
 44     inline complex(){
 45         r=i=0;
 46     }
 47     inline complex operator+(complex A)const{
 48         return complex(A.r+r,A.i+i);
 49     }
 50     inline complex operator-(complex A)const{
 51         return complex(r-A.r,i-A.i);
 52     }
 53     inline complex operator*(complex A)const{
 54         return complex(A.r*r-A.i*i,A.r*i+A.i*r);
 55     }
 56     inline void out(){
 57         if(abs(i)>esp) printf("%.2lf+%.2lfi
",r,i);
 58         else printf("%.2lf
",r+esp);
 59     }
 60 };
 61 int n,n1,n2,ans[maxn];
 62 complex A[maxn],B[maxn],_A[maxn],_B[maxn];
 63 char a[maxn],b[maxn];
 64 int init(int n){
 65     int tmp=1;while(tmp<n) tmp<<=1;
 66     return tmp;
 67 }
 68 int rev(int t,int l){
 69     int _t=0;
 70     for(int i=0;b(i)<l;i++){
 71         _t<<=1;if(t&b(i)) _t|=1;
 72     }
 73     return _t;
 74 }
 75 complex*FFT(complex X[],complex Y[],int t,int opt){
 76     rep(i,0,t-1) Y[rev(i,t)]=X[i];
 77     for(int s=2;s<=t;s<<=1){
 78         complex w1=complex(cos(2*pi/s),sin(2*pi*opt/s));
 79         for(int k=0;k<t;k+=s){
 80             complex w=complex(1,0);
 81             rep(i,k,k+(s>>1)-1){
 82                 complex t1=Y[i],t2=w*Y[i+(s>>1)];
 83                 Y[i]=t1+t2;Y[i+(s>>1)]=t1-t2;
 84                 w=w*w1;
 85             }
 86         }
 87     }
 88     if(opt==-1) rep(i,0,t-1) Y[i].r/=t,Y[i].i/=t;
 89     return Y; 
 90 }
 91 int main(){
 92     //freopen("#input.txt","r",stdin);
 93     //freopen("#output.txt","w",stdout);
 94     n=readint();
 95     readstr(a);readstr(b);
 96     while(a[n1]=='0') n1++;while(b[n2]=='0') n2++;
 97     rep(i,n1,n-1) A[i-n1].r=a[i]-'0';rep(i,n2,n-1) B[i-n2].r=b[i]-'0';
 98     n1=n-n1;n2=n-n2;
 99     int N=init(n);
100     FFT(A,_A,2*N,1);FFT(B,_B,2*N,1);
101     rep(i,0,2*N) _A[i]=_A[i]*_B[i];
102     FFT(_A,A,2*N,-1);
103     rep(i,0,2*N) ans[i+1]=floor(A[i].r+esp);
104     for(int i=2*N;i>=0;i--) if(ans[i]>9){
105         ans[i-1]+=ans[i]/10;ans[i]%=10;
106     }
107     int cnt=0;while(!ans[cnt]) cnt++;
108     rep(i,cnt,n1+n2-1) printf("%d",ans[i]);
109     //fclose(stdin);
110     //fclose(stdout);
111     return 0;
112 }
大数乘法 注意精度!
 1 #include<cstdio> 
 2 #include<cstring>
 3 #include<cmath>
 4 #include<ctime>
 5 #include<iostream>
 6 #include<algorithm>
 7 #include<queue>
 8 #include<stack>
 9 #include<set>
10 #define esp (1e-8)
11 #define maxint (2147483647)
12 #define pi (3.141592653589793)
13 #define l(a) ((a)<<1)
14 #define r(a) ((a)<<1|1)
15 #define b(a) (1<<(a))
16 #define rep(i,a,b) for(int i=a;i<=(b);i++)
17 #define clr(a) memset(a,0,sizeof(a))
18 typedef long long ll;
19 using namespace std;
20 int readint(){//只读入正整数 
21     int t=0;char c=getchar();
22     while(!isdigit(c)) c=getchar();
23     while(isdigit(c)){
24         t=(t<<3)+(t<<1)+c-'0';
25         c=getchar();
26     }
27     return t;
28 }
29 const int maxn=3000009;//注意maxn的取值 
30 int n,m;
31 struct complex{
32     double r,i;
33     inline complex(double R,double I){
34         r=R;i=I;
35     }
36     inline complex(){}
37     inline void out(){
38         if(abs(i)>esp) printf("%.2lf %.2lfi
",r,i);
39         else printf("%.2lf
",r+esp);
40     }
41     inline complex operator +(const complex A)const{
42         return complex(r+A.r,i+A.i);
43     }
44     inline complex operator -(const complex A)const{
45         return complex(r-A.r,i-A.i);
46     }
47     inline complex operator *(const complex A)const{
48         return complex(r*A.r-i*A.i,i*A.r+r*A.i);
49     }
50 };
51 int rev(int t,int len){
52     int ret=0;
53     for(int i=0;b(i)<len;i++){//求逆序->利用性质 
54         ret<<=1;if(t&b(i)) ret|=1;
55     }
56     return ret;
57 }
58 complex x1[maxn],x2[maxn],A[maxn],B[maxn];
59 void DFT(complex Ans[],complex a[],int t,int opt){
60     rep(i,0,t-1) Ans[rev(i,t)]=a[i];
61     for(int s=1;b(s)<=t;s++){//当前迭代计算的子列长度为b(s) 
62         int m=b(s);
63         complex w1=complex(cos(2*pi/m),sin(2*pi/m*opt));
64         for(int k=0;k<t;k+=m){//与递归一样的计算过程 
65             complex w=complex(1,0);
66             rep(j,0,(m>>1)-1){
67                 complex t1=Ans[k+j],t2=w*Ans[k+j+(m>>1)];
68                 Ans[k+j]=t1+t2;Ans[k+j+(m>>1)]=t1-t2;
69                 w=w*w1;
70             }
71         }
72     }
73     if(opt==-1) rep(i,0,t-1) Ans[i].r/=t,Ans[i].i/=t;
74 }
75 int main(){
76     //freopen("#intput.txt","r",stdin);
77     //freopen("#output.txt","w",stdout);
78     n=readint();m=readint();n++;m++;
79     rep(i,0,n-1) x1[i].r=readint();
80     rep(i,0,m-1) x2[i].r=readint();
81     int t=0,N=max(n,m);
82     while(b(t)<N) t++;N=b(t+1);
83     DFT(A,x1,N,1);DFT(B,x2,N,1);
84     rep(i,0,N-1) A[i]=A[i]*B[i];
85     DFT(B,A,N,-1);
86     rep(i,0,m+n-2){
87         printf("%.0lf",B[i].r+esp);
88         putchar(i==m+n-2?'
':' ');
89     }
90     //fclose(stdin);
91     //fclose(stdout);
92     return 0;
93 }
多项式乘法 迭代 n空间 nlogn时间 常数小

 uoj与洛谷都有题

注意几个点:

1、求rev

2、w从(1,0)开始

3、将n化为2^k

cnblogs.com/rvalue/p/7351400.html

原文地址:https://www.cnblogs.com/chensiang/p/7793046.html