zoukankan      html  css  js  c++  java
  • [Nescafé41]异化多肽(多项式求逆元)

    2015年的题,应该是将形式幂级数引入国内的元老级题目。

    大意:给定一个大小为m的正整数序列和n,问有多少种选法可以凑成n,每个数可以选多次,种类不同算不同方案。$n,m,C leqslant 100000$

    首先处理出生成函数$C$,设答案的形式幂级数为$F$,有递推式$F_n=sum F_{n-k}*C_k$。
    因为这个问题,导致完全不可以用分治解决了。所以我们重新从$C$的角度考虑:
    角度一:$$F=1+C+C^2+C^3+...=frac{1-C^infty}{1-C}$$角度二:$$F=FC+1$$最后都有:$$F=frac{1}{1-C}$$
    这样就是一个裸的多项式求逆问题了。
    模数$1005060097$的原根是$5$。多项式有无逆元取决于其常数项有无逆元,显然这题正好保证了$1-C$的常数项为$1$
    再次提醒:次数界开两倍,复杂度:$$T(n)=O(nlog n)+T(n/2)=O(nlog n)$$不过基于常数问题还是不要把它看成一个$log$比较好。

     1 #include<cstdio>
     2 #include<algorithm>
     3 #define rep(i,l,r) for (int i=l; i<=r; i++)
     4 using namespace std;
     5 
     6 const int N=400100,mod=1005060097,g=5;
     7 int n,m,x,rev[N],tmp[N],a[N],b[N],c[N],ic[N],lg[N];
     8 
     9 int ksm(int a,int b){
    10     int res;
    11     for (res=1; b; a=1ll*a*a%mod,b>>=1)
    12         if (b & 1) res=1ll*res*a%mod;
    13     return res;
    14 }
    15 
    16 void DFT(int a[],int n,int f){
    17     for (int i=0; i<n; i++) if (i<rev[i]) swap(a[i],a[rev[i]]);
    18     for (int i=1; i<n; i<<=1){
    19         int wn=ksm(g,(f==1) ? (mod-1)/(i<<1) : (mod-1)-(mod-1)/(i<<1));
    20         for (int p=i<<1,j=0; j<n; j+=p){
    21             int w=1;
    22             for (int k=0; k<i; k++,w=1ll*w*wn%mod){
    23                 int x=a[j+k],y=1ll*w*a[i+j+k]%mod; a[j+k]=(x+y)%mod; a[i+j+k]=(x-y+mod)%mod;
    24             }
    25         }
    26     }
    27     if (f==1) return;
    28     int inv=ksm(n,mod-2);
    29     for (int i=0; i<n; i++) a[i]=1ll*a[i]*inv%mod;
    30 }
    31 
    32 void get(int a[],int b[],int l){
    33     if (l==1){ b[0]=ksm(a[0],mod-2); return; }
    34     get(a,b,l>>1); int n=l<<1;
    35     for (int i=0; i<l; i++) tmp[i]=a[i],tmp[i+l]=0;
    36     for (int i=0; i<n; i++) rev[i]=(rev[i>>1]>>1)|((i&1)<<(lg[n]-1));
    37     DFT(tmp,n,1); DFT(b,n,1);
    38     for (int i=0; i<n; i++) tmp[i]=1ll*b[i]*(2-1ll*tmp[i]*b[i]%mod+mod)%mod;
    39     DFT(tmp,n,-1);
    40     for (int i=0; i<l; i++) b[i]=tmp[i],b[i+l]=0;
    41 }
    42 
    43 int main(){
    44     freopen("polypeptide.in","r",stdin);
    45     freopen("polypeptide.out","w",stdout);
    46     scanf("%d%d",&n,&m); c[0]=1;
    47     rep(i,2,n<<2) lg[i]=lg[i>>1]+1;
    48     rep(i,1,m) scanf("%d",&x),c[x]++;
    49     rep(i,1,n) c[i]=mod-c[i];
    50     for (m=1; m<=n; m<<=1); get(c,ic,m);
    51     printf("%d
    ",ic[n]);
    52     return 0;
    53 }

     

  • 相关阅读:
    Java基础之Comparable与Comparator
    Java基础之访问权限控制
    Java基础之抽象类与接口
    Java基础之多态和泛型浅析
    Spring MVC入门
    Spring框架之事务管理
    伸展树(Splay Tree)进阶
    2018牛客网暑期ACM多校训练营(第三场) A
    2018牛客网暑期ACM多校训练营(第三场) H
    HDU 6312
  • 原文地址:https://www.cnblogs.com/HocRiser/p/8776970.html
Copyright © 2011-2022 走看看