COGS 2259 异化多肽——生成函数+多项式求逆
题目:http://cogs.pro:8080/cogs/problem/problem.php?pid=2259
详见:https://www.cnblogs.com/Zinn/p/10054569.html
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define ll long long using namespace std; const int N=1e5+5,M=(1<<18)+5,mod=1005060097,g=5; int n,a[M],b[M],A[M],len,r[M],c[M]; int rdn() { int ret=0;bool fx=1;char ch=getchar(); while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();} while(ch>='0'&&ch<='9') ret=ret*10+ch-'0',ch=getchar(); return fx?ret:-ret; } void upd(int &x){x>=mod?x-=mod:0;} int pw(int x,int k) {int ret=1;while(k){if(k&1)ret=(ll)ret*x%mod;x=(ll)x*x%mod;k>>=1;}return ret;} void ntt(int *a,bool fx) { for(int i=0;i<len;i++) if(i<r[i])swap(a[i],a[r[i]]); for(int R=2;R<=len;R<<=1) { int wn=pw( g,fx?(mod-1)-(mod-1)/R:(mod-1)/R ); for(int i=0,m=R>>1;i<len;i+=R) for(int j=0,w=1;j<m;j++,w=(ll)w*wn%mod) { int x=a[i+j], y=(ll)w*a[i+m+j]%mod; a[i+j]=x+y; upd(a[i+j]); a[i+m+j]=x+mod-y; upd(a[i+m+j]); } } if(!fx)return ; int inv=pw(len,mod-2); for(int i=0;i<len;i++)a[i]=(ll)a[i]*inv%mod; } void getinv(int n,int *a,int *b) { if(n==1){b[0]=pw(a[0],mod-2);return;} getinv(n+1>>1,a,b); for(len=1;len<n<<1;len<<=1); for(int i=0;i<len;i++)r[i]=(r[i>>1]>>1)+((i&1)?len>>1:0); for(int i=0;i<n;i++)A[i]=a[i]; for(int i=n;i<len;i++)A[i]=0; ntt(A,0); ntt(b,0); for(int i=0;i<len;i++)b[i]=(2-(ll)A[i]*b[i])%mod*b[i]%mod+mod,upd(b[i]); ntt(b,1); for(int i=n;i<len;i++)b[i]=0; } int main() { freopen("polypeptide.in","r",stdin); freopen("polypeptide.out","w",stdout); n=rdn();int m;m=rdn(); for(int i=1,d;i<=m;i++) { d=rdn(); a[d]+=mod-1,upd(a[d]); } a[0]++; upd(a[0]); getinv(n+1,a,b); printf("%d\n",b[n]); return 0; }