UOJ#269. 【清华集训2016】如何优雅地求和(FFT)

传送门

题解:
f f f二项式变换一下就行了,变换可以用二项式反演。

#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';
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值