题目:
题解:
首先一看这不是指数生成函数,对于每一个氨基酸整一个生成函数,x^(Ci的倍数)。
但我们发现这个东西没法化简&优化,复杂度过不去
换个思路,我们把所有的氨基酸搞成一个生成函数,x^k的系数为相对分子质量为k的氨基酸有多少个,设为A(x),答案的多项式为B(x),那么
那么我们只需要求1-A(x)的逆就好了
多项式求逆?
一个【多项式的逆】定义为对于一个多项式
A(x)
A
(
x
)
其逆
A−1(x)
A
−
1
(
x
)
设为
B(x)
B
(
x
)
A(x)B(x)≡1(%xn)
A
(
x
)
B
(
x
)
≡
1
(
%
x
n
)
求法?
分类讨论
当n=1的时候,
A(x)≡c(%x)
A
(
x
)
≡
c
(
%
x
)
,那么
A−1(x)=c−1
A
−
1
(
x
)
=
c
−
1
当n>1的时候,设 A(x)B(x)≡1(%xn) A ( x ) B ( x ) ≡ 1 ( % x n )
移项 A(x)B(x)−1≡0(%xn) A ( x ) B ( x ) − 1 ≡ 0 ( % x n )
两边平方 A2(x)B2(x)+1−2A(x)B(x)≡0(%x2n) A 2 ( x ) B 2 ( x ) + 1 − 2 A ( x ) B ( x ) ≡ 0 ( % x 2 n )
设 C(x)A(x)≡1(%x2n) C ( x ) A ( x ) ≡ 1 ( % x 2 n )
对刚才那个柿子两边乘 C(x) C ( x ) ,得 B2(x)A(x)+C(x)−2B(x)≡0(%x2n) B 2 ( x ) A ( x ) + C ( x ) − 2 B ( x ) ≡ 0 ( % x 2 n )
移项 C(x)=B(x)(2−B(x)A(x)) C ( x ) = B ( x ) ( 2 − B ( x ) A ( x ) )
可以发现C是下一层的B,那我们写的时候C是中转,A是固定的,每次我们要把A复制给C,然后直接处理B就好了
我们可以通过递归来求,时间复杂度T(n)=T(n/2)+nlogn=nlogn,多项式乘法用NTT
NTT的时候,有一个快速幂的原根,是模数的原根,而这个很大模数的原根是5
数据范围瞎给!
代码:
#include <cstdio>
#include <iostream>
#include <algorithm>
#define LL long long
using namespace std;
const int N=1400000;
const int mod=1005060097;
LL a[N],b[N],c[N];int r[N*2];
LL ksm(LL a,LL k)
{
LL ans=1;
for (;k;k>>=1,a=a*a%mod)
if (k&1) ans=ans*a%mod;
return ans;
}
void NTT(int n,LL *a,int id)
{
int L=0;for (int i=1;i<n;i<<=1) ++L;
for (int i=0;i<=n;i++) r[i]=(r[i>>1]>>1)|((i&1)<<L-1);
for (int i=0;i<n;i++)
if (i<r[i]) swap(a[i],a[r[i]]);
for (int k=1;k<n;k<<=1)
{
LL wn=ksm(5,(mod-1)/(k<<1));
for (int i=0;i<n;i+=(k<<1))
{
LL w=1;
for (int j=0;j<k;j++,w=w*wn%mod)
{
LL x=a[i+j],y=w*a[i+j+k]%mod;
a[i+j]=(x+y)%mod; a[i+j+k]=(x-y+mod)%mod;
}
}
}
if (id==-1) reverse(a+1,a+n);
}
void INV(int n,LL *a,LL *b,LL *c)
{
if (n==1)
{
b[0]=ksm(a[0],mod-2);
return;
}
INV((n+1)>>1,a,b,c);int now=1;
for (now=1;now<(n<<1);now<<=1);
for (int i=0;i<n;i++) c[i]=a[i];
for (int i=n;i<now;i++) c[i]=0;
NTT(now,c,1); NTT(now,b,1);
for (int i=0;i<=now;i++) b[i]=(2-b[i]*c[i]%mod+mod)%mod*b[i]%mod;
NTT(now,b,-1);
LL inv=ksm(now,mod-2);
for (int i=0;i<n;i++) b[i]=b[i]*inv%mod;
for (int i=n;i<now;i++) b[i]=0;
}
int main()
{
freopen("polypeptide.in","r",stdin);
freopen("polypeptide.out","w",stdout);
int e,m;scanf("%d%d",&e,&m);int maxx=0;
for (int i=1;i<=m;i++)
{
int x;scanf("%d",&x);
if (x<=e) a[x]=(a[x]-1+mod)%mod;
maxx=max(maxx,x);
}
a[0]=1;int n,L=0;
for (n=1;n<=maxx*2;n<<=1) L++;
INV(n,a,b,c);
printf("%lld",b[e]%mod);
}