• COGS2259 异化多肽


    传送门

    听说是多项式求逆的模板题,以后不怕没地方练多项式求逆啦哈哈……

    ……

    我们设使用一个氨基酸能组成质量为$n$的多肽数量这个数列为${a_n}$,设它的生成函数为$A(x)$,显然有

    egin{align}A(x)=sum_{i=0}^infty sum_{j=0}^m[C_j=i]end{align}

    即$A(x)$的$i$次方系数即为相对分子质量为$i$的氨基酸数量。

    我们要求的是一个数列${b_n}$,它的第$n$项即为使用任意数目的氨基酸能组成质量为$n$的多肽数量,设它的生成函数为$B(x)$,那么有

    egin{align}A(x)=sum_{i=0}^infty B(x)^iend{align}

    右边化成封闭形式,得

    egin{align}A(x)=frac 1{1-B(x)}end{align}

    多项式求逆即可,答案即为$[x^n]A(x)$。顺便一提,1005060097的原根是5。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 const int maxn=262200,p=1005060097,g=5;
     6 void NTT(int*,int,int);
     7 void getinv(int*,int*,int);
     8 int qpow(int,int,int);
     9 int n,m,N=1,x,A[maxn]={0},B[maxn];
    10 int main(){
    11     freopen("polypeptide.in","r",stdin);
    12     freopen("polypeptide.out","w",stdout);
    13     scanf("%d%d",&n,&m);
    14     while(N<=n)N<<=1;
    15     while(m--){
    16         scanf("%d",&x);
    17         A[x]=(A[x]+p-1)%p;
    18     }
    19     A[0]=(A[0]+1)%p;
    20     getinv(A,B,N);
    21     printf("%d",B[n]);
    22     return 0;
    23 }
    24 void NTT(int *A,int n,int tp){
    25     for(int i=1,j=0,k;i<n-1;i++){
    26         k=n;
    27         do j^=(k>>=1);while(j<k);
    28         if(i<j)swap(A[i],A[j]);
    29     }
    30     for(int k=2;k<=n;k<<=1){
    31         int wn=qpow(g,(tp>0?(p-1)/k:(p-1)/k*(long long)(p-2)%(p-1)),p);
    32         for(int i=0;i<n;i+=k){
    33             int w=1;
    34             for(int j=0;j<(k>>1);j++,w=(long long)w*wn%p){
    35                 int a=A[i+j],b=(long long)w*A[i+j+(k>>1)]%p;
    36                 A[i+j]=(a+b)%p;
    37                 A[i+j+(k>>1)]=(a-b+p)%p;
    38             }
    39         }
    40     }
    41     if(tp<0){
    42         int inv=qpow(n,p-2,p);
    43         for(int i=0;i<n;i++)A[i]=(long long)A[i]*inv%p;
    44     }
    45 }
    46 void getinv(int *A,int *C,int n){
    47     static int B[maxn];
    48     fill(C,C+n,0);
    49     C[0]=qpow(A[0],p-2,p);
    50     for(int k=2;k<=n;k<<=1){
    51         copy(A,A+k,B);
    52         fill(B+k,B+(k<<1),0);
    53         NTT(B,k<<1,1);
    54         NTT(C,k<<1,1);
    55         for(int i=0;i<(k<<1);i++)C[i]=C[i]*((2-((long long)B[i]*C[i]%p)+p)%p)%p;
    56         NTT(C,k<<1,-1);
    57         fill(C+k,C+(k<<1),0);
    58     }
    59 }
    60 int qpow(int a,int b,int p){
    61     int ans=1;
    62     for(;b;b>>=1,a=(long long)a*a%p)if(b&1)ans=(long long)ans*a%p;
    63     return ans;
    64 }
    View Code

    其实我对NTT和生成函数只是刚入门而已……我们的征途是星辰大海……

  • 相关阅读:
    npx小工具
    2015 Multi-University Training Contest 1
    字符串 --- KMP Eentend-Kmp 自动机 trie图 trie树 后缀树 后缀数组
    AC自动机
    AC自动机
    区间合并 --- Codeforces 558D : Gess Your Way Out ! II
    暴力 + 贪心 --- Codeforces 558C : Amr and Chemistry
    计数排序 + 线段树优化 --- Codeforces 558E : A Simple Task
    Ubuntu 16.04 安装mysql并设置远程访问
    数学 --- 高斯消元 POJ 1830
  • 原文地址:https://www.cnblogs.com/hzoier/p/6424924.html
Copyright © 2020-2023  润新知