• 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
  • 相关阅读:
    jQuery基础---filter()和find()
    js数组去重的4个方法
    各种排序算法的分析及java实现
    js三种对话框
    js数组与字符串的相互转换
    java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result异常的解决方法
    Django REST framework视图
    Django REST framework序列化
    Django REST framework简介
    Django REST framework认证、权限、频率
  • 原文地址:https://www.cnblogs.com/wls001/p/10031749.html
Copyright © 2020-2023  润新知