1. 程式人生 > >洛谷3711:倉鼠的數學題(NTT+伯努利數)

洛谷3711:倉鼠的數學題(NTT+伯努利數)

題面
題意:給出a陣列,求
nk=0Sk(x)ak
所表示多項式的每一項係數。

額,直接將伯努利數帶進S裡,得

=k=0nakk+1g=0kCgk+1Bgxk+1g=k=0nakk!g=0nBgg!xk+1g(k+1g)!
設c=k+1-g,則xc的係數為1c!k+1g==cakk!Bgg!
就是個卷積了。

到處膜拜大佬們的程式,總算把我程式搞對了
但有兩個似乎很重要的問題還不懂。

①樣例是客觀存在的,我推的公式也和題解一樣
為什麼B1要等於12

B+B又是什麼東西

#include <iostream>
#include <fstream>
#include <algorithm> #include <cmath> #include <ctime> #include <cstdio> #include <cstdlib> #include <cstring> using namespace std; #define mmst(a, b) memset(a, b, sizeof(a)) #define mmcp(a, b) memcpy(a, b, sizeof(b)) typedef long long LL; const int N=1001000; const LL mo=998244353
; LL I[N],jc[N],Ijc[N]; LL E[N],D[N],B[N],F[N]; int n,rev[N]; LL cheng(LL a,LL b) { LL res=1; for(;b;b>>=1,a=a*a%mo) if(b&1) res=res*a%mo; return res; } void init(int lim) { int k=-1; n=1; while(n<lim) n<<=1,k++; for(int i=0;i<n;i++) rev[i]=(rev[i>>1
]>>1) | ((i&1)<<k); } void ntt(LL *a,int ops) { for(int i=0;i<n;i++) if(i<rev[i]) swap(a[i],a[rev[i]]); for(int l=2;l<=n;l<<=1) { int m=l>>1; LL wn=(ops) ? cheng(3,(mo-1)/l) : cheng(3,mo-1-(mo-1)/l); for(int i=0;i<n;i+=l) { LL w=1; for(int k=0;k<m;k++) { LL t=a[i+k+m]*w%mo; a[i+k+m]=(a[i+k]-t+mo)%mo; a[i+k]=(a[i+k]+t)%mo; w=w*wn%mo; } } } if(!ops) for(int i=0;i<n;i++) a[i]=a[i]*I[n]%mo; } void ny(int x) { if(x==1) return; ny(x/2); for(int i=0;i<x;i++) E[i]=B[i]; init(x*2); ntt(E,1); ntt(D,1); for(int i=0;i<n;i++) D[i]=D[i]*(2-E[i]*D[i]%mo+mo)%mo; ntt(D,0); for(int i=0;i<n;i++) E[i]=0; for(int i=x;i<n;i++) D[i]=0; } LL nn,aa[N]; int main() { I[1]=Ijc[0]=jc[0]=1; for(int i=2;i<N;i++) I[i]=I[mo%i]*(mo-mo/i)%mo; for(int i=1;i<N;i++) jc[i]=jc[i-1]*i%mo,Ijc[i]=Ijc[i-1]*I[i]%mo; cin>>nn; for(int i=0;i<=nn;i++) scanf("%lld",&aa[i]),aa[i]=aa[i]*jc[i]%mo; printf("%lld ",aa[0]); for(int i=0;i<=nn+1;i++) B[i]=Ijc[i+1]; init(nn+1); D[0]=1; ny(n); for(int i=nn+1;i<N;i++) D[i]=0; D[1]=499122177; mmcp(F,D); mmst(D,0); for(int i=0;i<=nn;i++) D[nn+1-i]=F[i]; init(nn+nn+3); ntt(D,1); ntt(aa,1); for(int i=0;i<n;i++) D[i]=D[i]*aa[i]%mo; ntt(D,0); for(int i=1;i<=nn+1;i++) printf("%lld ",D[i+nn]*Ijc[i]%mo); cout<<endl; return 0; }