1. 程式人生 > >uoj#269. 【清華集訓2016】如何優雅地求和(FFT)

uoj#269. 【清華集訓2016】如何優雅地求和(FFT)

傳送門

題解: 把ff二項式變換一下就行了,變換可以用二項式反演。

#include <bits/stdc++.h>
using namespace std;

const int RLEN=1<<18|1;
inline char nc() {
	static char ibuf[RLEN],*ib,*ob;
	(ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
	return (ib==ob) ? -1 : *ib++;
}
inline int rd() {
	char ch=nc(); int
i=0,f=1; while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();} while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();} return i*f; } const int N=2e5+50, mod=998244353; inline int add(int x,int y) {return (x+y>=mod) ? (x+y-mod) : (x+y);} inline int dec(int x,int y) {return (x-y<0) ? (x-y+mod)
: (x-y);} inline int mul(int x,int y) {return (long long)x*y%mod;} inline int power(int a,int b,int rs=1) {for(;b;b>>=1,a=mul(a,a)) if(b&1) rs=mul(rs,a); return rs;} inline int cinv(int a) {return power(a,mod-2);} int n,m,k,x,a[N],b[N],w[N],pos[N]; struct combin { int fac[N],ifac[N],dn[
N]; inline void init() { fac[0]=1; for(int i=1;i<=m;i++) fac[i]=mul(fac[i-1],i); ifac[m]=cinv(fac[m]); for(int i=m-1;~i;i--) ifac[i]=mul(ifac[i+1],i+1); dn[0]=1; for(int i=1;i<=m;i++) dn[i]=mul(dn[i-1],dec(n+1,i)), dn[i]=mul(dn[i],cinv(i)); } } C; inline void init(int nn) { for(k=1;k<=nn;k<<=1); for(int i=1;i<k;i++) pos[i]=(i&1) ? ((pos[i>>1]>>1)^(k>>1)) : (pos[i>>1]>>1); } inline void dft(int *A,int o=1) { for(int i=1;i<k;i++) if(pos[i]>i) swap(A[i],A[pos[i]]); for(int bl=1;bl<k;bl<<=1) { int tl=bl<<1, wn=power(3,(mod-1)/tl); w[0]=1; for(int i=1;i<bl;i++) w[i]=mul(w[i-1],wn); for(int bg=0;bg<k;bg+=tl) for(int j=0;j<bl;j++) { int &t1=A[bg+j], &t2=A[bg+j+bl], t=mul(t2,w[j]); t2=dec(t1,t); t1=add(t1,t); } } if(!~o) { const int inv=cinv(k); for(int i=0;i<k;i++) a[i]=mul(a[i],inv); reverse(a+1,a+k); } } int main() { n=rd(), m=rd(), x=rd(); C.init(); for(int i=0;i<=m;i++) b[i]=mul(rd(),C.ifac[i]); for(int i=0;i<=m;i++) a[i]=mul((i&1)?mod-1:1,C.ifac[i]); init(m*2); dft(a); dft(b); for(int i=0;i<k;i++) a[i]=mul(a[i],b[i]); dft(a,-1); for(int i=0;i<=m;i++) a[i]=mul(a[i],C.fac[i]); int ans=0; for(int i=0,v=1;i<=m;i++) ans=add(ans,mul(C.dn[i],mul(a[i],v))), v=mul(v,x); cout<<ans<<'\n'; }