【多项式】【生成函数】51nod1514 美妙的序列
作者:互联网
分析:
感觉生成函数在这有点大材小用了。。。。
这个合法的序列就是指任意一个前缀都不能是1-i的排列
设f(n)表示用前n个数组成的合法排列个数。
那么f(n)=n!−∑i=0i<nf(i)∗(n−i)!
移项∑i=0i≤nf(i)=n!
所以设g(x)=i!xi
所以f(x)∗g(x)=g(x)−1
这个-1是因为当x=0时,右式0!=1,而左式f(0)=0,所以f(0)×g(0)=0
所以就可以利用生成函数的性质:
f(x)=1−g(x)1
多项式求逆即可
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<cmath>
#define SF scanf
#define PF printf
#define MAXN 400010
#define MOD 998244353
using namespace std;
typedef long long ll;
const int G=3;
ll g1[MAXN],g[MAXN],f[MAXN];
ll fsp(ll x,int y){
ll res=1;
while(y){
if(y&1)
res=res*x%MOD;
x=x*x%MOD;
y>>=1;
}
return res;
}
void NTT(ll A[],int N,int flag){
for(int i=1,j=0;i<N;i++){
for(int d=N;j^=d>>=1,~j&d;);
if(i<j)
swap(A[i],A[j]);
}
for(int i=1;i<N;i<<=1){
ll wn=fsp(G,(MOD-1)/(i<<1));
if(flag)
wn=fsp(wn,MOD-2);
for(int j=0;j<N;j+=(i<<1)){
ll w=1;
for(int k=0;k<i;k++,w=w*wn%MOD){
ll x=A[j+k],y=A[i+j+k]*w%MOD;
A[j+k]=(x+y)%MOD;
A[i+j+k]=(x-y+MOD)%MOD;
}
}
}
if(flag){
ll invN=fsp(N,MOD-2);
for(int i=0;i<N;i++)
A[i]=A[i]*invN%MOD;
}
}
void inv(int N,ll A[],ll B[]){
if(N==1){
B[0]=fsp(A[0],MOD-2);
return;
}
inv((N+1)>>1,A,B);
static ll tmp[MAXN];
for(int i=0;i<N;i++)
tmp[i]=A[i];
int p=1;
while(p<=N*2)
p<<=1;
NTT(tmp,p,0);
NTT(B,p,0);
for(int i=0;i<p;i++)
B[i]=B[i]*(2-tmp[i]*B[i]%MOD+MOD)%MOD;
NTT(B,p,1);
for(int i=N;i<p;i++) B[i]=0;
for(int i=0;i<p;i++) tmp[i]=0;
}
int main(){
int n=100001,t;
g[0]=1;
for(int i=1;i<n;i++)
g[i]=g[i-1]*i%MOD;
inv(n,g,g1);
for(int i=0;i<n;i++)
f[i]=MOD-g1[i];
f[0]=(f[0]+1)%MOD;//f[0]=0;
SF("%d",&t);
while(t--){
SF("%d",&n);
PF("%lld\n",f[n]);
}
}
标签:51nod1514,int,多项式,ll,美妙,MAXN,res,include,define 来源: https://blog.csdn.net/qq_34454069/article/details/88831045