FFT模板 生成函数 原根 多项式求逆 多项式开根

FFT
 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdlib>
 4 #include<cstdio>
 5 #include<cmath>
 6 #include<algorithm>
 7 #define maxn 1000005
 8 using namespace std;
 9 inline int read() {
10     int x=0,f=1;char ch=getchar();
11     for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1;
12     for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
13     return x*f;
14 }
15 double pi=acos(-1.0);
16 struct complex {
17     double x,y;
18     complex (double xx=0,double yy=0) {x=xx;y=yy;}
19     complex operator +(const complex b) const {return complex(x+b.x,y+b.y);}
20     complex operator -(const complex b) const {return complex(x-b.x,y-b.y);}
21     complex operator *(const complex b) const {return complex(x*b.x-y*b.y,x*b.y+y*b.x);}
22 }a[maxn],b[maxn];
23 int n,m;
24 int limit=1,l,pos[maxn];
25 void FFT(complex *A,int tp) {
26     for(int i=0;i<limit;i++) if(i<pos[i]) swap(A[i],A[pos[i]]);
27     for(int mid=1;mid<limit;mid<<=1) {
28         complex wn(cos(pi/mid),tp*sin(pi/mid));
29         for(int R=mid<<1,j=0;j<limit;j+=R) {
30             complex w(1,0);
31             for(int k=0;k<mid;k++,w=w*wn) {
32                 complex x=A[j+k],y=w*A[j+mid+k];
33                 A[j+k]=x+y;
34                 A[j+mid+k]=x-y;
35             }
36         }
37     }
38     return ;
39 }
40 int main() {
41     n=read(),m=read();
42     for(int i=0;i<=n;i++) a[i].x=read();
43     for(int i=0;i<=m;i++) b[i].x=read();
44     while(limit<=n+m) limit<<=1,l++;
45     for(int i=0;i<limit;i++) pos[i]=(pos[i>>1]>>1)|((i&1)<<(l-1));
46     FFT(a,1);
47     FFT(b,1);
48     for(int i=0;i<limit;i++) a[i]=a[i]*b[i];
49     FFT(a,-1);
50     for(int i=0;i<=n+m;i++) printf("%d ",(int)(a[i].x/limit+0.5));
51 }
FFT

 

 生成函数

小A有ai个价值为Ai的物品,小B有bi个价值为Ai的物品,求用两个组成价值为ci的方案数

生成函数可以解决上面的这个问题,构造两个多项式,第X的Ai次方项的系数表示价值为i的物品有多少个,对两个人分别构造,乘在一起的多项式就代表所有的方案数。

 

原根

定义P的原根为满足的整数g。 

 

NTT

 

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdlib>
 4 #include<cstdio>
 5 #include<cmath>
 6 #include<algorithm>
 7 #define maxn 4000001
 8 #define mod 998244353
 9 #define ll long long 
10 using namespace std;
11 inline int read() {
12     int x=0,f=1;char ch=getchar();
13     for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1;
14     for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
15     return x*f;
16 }
17 ll a[maxn],b[maxn],pos[maxn];
18 ll n,m,limit=1,l,g=3;
19 ll power(ll x,ll y) {
20     ll ans=1;
21     while(y) {
22         if(y&1) ans*=x,ans%=mod;
23         x*=x,x%=mod;y>>=1;
24     }
25     return ans;
26 }
27 void NTT(ll *A,int tp) {
28     for(int i=0;i<limit;i++) if(i<pos[i]) swap(A[i],A[pos[i]]);
29     for(int mid=1;mid<limit;mid<<=1) {
30         ll wn=power(g,(mod-1)/(mid<<1));
31         if(tp==-1) wn=power(wn,mod-2);
32         for(int j=0;j<limit;j+=(mid<<1)) {
33             ll w=1;
34             for(int k=0;k<mid;k++,w*=wn,w%=mod) {
35                 ll x=A[j+k],y=w*A[j+mid+k];
36                 A[j+k]=x+y;A[j+k]=(A[j+k]%mod+mod)%mod;
37                 A[j+mid+k]=x-y;A[j+mid+k]=(A[j+mid+k]%mod+mod)%mod;
38             }
39         }
40     }
41     if(tp==-1) {
42         ll ny=power(limit,mod-2);
43         for(int i=0;i<limit;i++) A[i]*=ny,A[i]=(A[i]%mod+mod)%mod;
44     }
45 }
46 int main() {
47     n=read(),m=read();
48     for(int i=0;i<=n;i++) a[i]=read();
49     for(int i=0;i<=m;i++) b[i]=read();
50     while(limit<=n+m) limit<<=1,l++;
51     for(int i=0;i<limit;i++) pos[i]=(pos[i>>1]>>1)|((i&1)<<(l-1));
52     NTT(a,1);
53     NTT(b,1);
54     for(int i=0;i<limit;i++) a[i]=a[i]*b[i],a[i]=(a[i]%mod+mod)%mod;
55     NTT(a,-1);
56     for(int i=0;i<=n+m;i++) printf("%lld ",a[i]);
57 }
NTT

 

多项式求逆

 

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdlib>
 4 #include<cstdio>
 5 #include<cmath>
 6 #include<algorithm>
 7 #define ll long long
 8 #define mod 998244353
 9 #define maxn 1000000
10 using namespace std;
11 inline int read() {
12     int x=0,f=1;char ch=getchar();
13     for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1;
14     for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
15     return x*f;
16 }
17 ll g=3,limit=1,l,n;
18 ll a[maxn],b[maxn],pos[maxn],c[maxn];
19 ll power(ll x,ll y) {
20     ll ans=1;
21     while(y) {
22         if(y&1) ans*=x,ans%=mod;
23         x*=x,x%=mod;y>>=1;
24     }
25     return ans;
26 }
27 void NTT(ll *A,int tp) {
28     for(int i=0;i<limit;i++) if(i<pos[i]) swap(A[i],A[pos[i]]);
29     for(int mid=1;mid<limit;mid<<=1) {
30         ll wn=power(g,(mod-1)/(mid<<1));
31         if(tp==-1) wn=power(wn,mod-2);
32         for(int j=0;j<limit;j+=(mid<<1)) {
33             ll w=1;
34             for(int k=0;k<mid;k++,w*=wn,w%=mod) {
35                 ll x=A[j+k],y=w*A[j+mid+k]%mod;
36                 A[j+k]=x+y;A[j+k]=(A[j+k]%mod+mod)%mod;
37                 A[j+mid+k]=x-y;A[j+mid+k]=(A[j+mid+k]%mod+mod)%mod;
38             }
39         }
40     }
41     if(tp==-1) {
42         ll ny=power(limit,mod-2);
43         for(int i=0;i<limit;i++) A[i]*=ny,A[i]=(A[i]%mod+mod)%mod;
44     }
45 }
46 int d[maxn];
47 void inv(int step,ll *A,ll *B) {
48     if(step==1) {B[0]=power(A[0],mod-2);return;}
49     inv((step+1)>>1,A,B);
50     l=0,limit=1;
51     while(limit<=(step<<1)) limit<<=1,l++;
52     for(int i=0;i<limit;i++) pos[i]=(pos[i>>1]>>1)|((i&1)<<(l-1));
53     for(int i=0;i<step;i++) c[i]=A[i];
54     for(int i=step;i<limit;i++) c[i]=0;
55     NTT(c,1);NTT(B,1);
56     for(int i=0;i<limit;i++) B[i]=((2ll-c[i]*B[i]%mod)+mod)%mod*B[i]%mod;
57     NTT(B,-1);
58     for(int i=step;i<limit;i++) B[i]=0;
59 }
60 int main() {
61     n=read();
62     for(int i=0;i<n;i++) a[i]=read();
63     inv(n,a,b);
64     for(int i=0;i<n;i++) printf("%lld ",b[i]);
65 }
多项式求逆

 

 

多项式开根

 1 void getsqr(ll *A,ll *B,ll len) {
 2     if(len==1) {B[0]=1;return;}
 3     getsqr(A,B,(len+1)>>1);
 4     memset(invb,0,sizeof(invb));
 5     getinv(B,invb,len);
 6     l=0,limit=1;
 7     while(limit<=(len<<1)) limit<<=1,l++;
 8     for(int i=0;i<limit;i++) pos[i]=(pos[i>>1]>>1)|((i&1)<<(l-1));
 9     for(int i=0;i<len;i++) c[i]=A[i];
10     for(int i=len;i<limit;i++) c[i]=0;
11     NTT(invb,1);NTT(c,1);NTT(B,1);
12     for(int i=0;i<limit;i++) {B[i]=((c[i]*invb[i]%mod)*inv2%mod+B[i]*inv2)%mod;}
13     NTT(B,-1);
14     for(int i=len;i<limit;i++) B[i]=0;
15 }
View Code

 

posted @ 2018-11-28 14:26  wls001  阅读(318)  评论(0编辑  收藏  举报