COGS2259 异化多肽

传送门

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

……

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

\begin{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)$,那么有

\begin{align}A(x)=\sum_{i=0}^\infty B(x)^i\end{align}

右边化成封闭形式,得

\begin{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和生成函数只是刚入门而已……我们的征途是星辰大海……

posted @ 2017-02-21 16:50  AntiLeaf  阅读(147)  评论(0编辑  收藏  举报