【题解】【清华集训2016】如何优雅地求和

【清华集训2016】如何优雅地求和

( ext{Solution:})

[sum_{k=0}^n f(k)inom{n}{k}x^k (1-x)^{n-k} \ =sum_{j=0}^m a_jsum_{k=0}^n k^i inom{n}{k}x^k (1-x)^{n-k} \ =sum_{i=0}^m a_isum_{k=0}^n sum_{j=0}^k inom{k}{j}j!{irace j}inom{n}{k}x^k (1-x)^{n-k} \ =sum_{i=0}^m a_isum_{k=0}^n sum_{j=0}^k j!{irace j}inom{n}{j}inom{n-j}{k-j}x^k (1-x)^{n-k} \ =sum_{i=0}^m a_isum_{k=0}^n sum_{j=0}^k n^{underline{j}}{irace j}inom{n-j}{k-j}x^k (1-x)^{n-k} \ =sum_{i=0}^m a_isum_{j=0}^n n^{underline{j}}{irace j} sum_{k=j}^n inom{n-j}{k-j}x^k (1-x)^{n-k} \ =sum_{i=0}^m a_isum_{j=0}^n n^{underline{j}}{irace j} sum_{k=0}^{n-j} inom{n-j}{k}x^{k+j} (1-x)^{n-k-j} \ =sum_{i=0}^m a_isum_{j=0}^n n^{underline{j}}{irace j} left(frac{1-x}{x} ight)^{-j} sum_{k=0}^{n-j} inom{n-j}{k}x^{k} (1-x)^{n-k} \ =sum_{i=0}^m a_isum_{j=0}^n n^{underline{j}}{irace j} left(frac{1-x}{x} ight)^{-j} (1-x)^n sum_{k=0}^{n-j} inom{n-j}{k}left(frac{x}{1-x} ight)^k \ =sum_{i=0}^m a_isum_{j=0}^n n^{underline{j}}{irace j} left(frac{1-x}{x} ight)^{-j} (1-x)^n left(frac{1}{1-x} ight)^{n-j} ]

注意不要把最后的 (x,1-x) 合并到一起看成 (1,) 实际上并不是 (1,) 其指数和并不是 (n-j.)

没有写多项式,写了部分分。

#include<bits/stdc++.h>
using namespace std;
const int N=8010;
int s[N][N];
int n,m,xx,a[N],r[N];
int low[N],b[N],inv[N];
typedef long long ll;
const int mod=998244353;
const int P=998244353;
inline int Add(int x,int y){return (x+y)%mod;}
inline int Mul(int x,int y){return 1ll*x*y%mod;}
inline int Dec(int x,int y){return (x-y+mod)%mod;}
inline int Max(int x,int y){return x>y?x:y;}
inline int Min(int x,int y){return x<y?x:y;}
inline int Abs(int x){if(x<0)x=-x;return x;}
inline int read(){
	int s=0,w=1;
	char ch=getchar();
	while(!isdigit(ch)){
		if(ch=='-')w=-1;
		ch=getchar();
	}
	while(isdigit(ch)){
		s=s*10+ch-'0';
		ch=getchar();
	}
	return s*w;
}
inline int qpow(int x,int y){
	int res=1;
	while(y){
		if(y&1)res=Mul(res,x);
		x=Mul(x,x);y>>=1;
	}
	return res;
}
namespace Interpolation{
	int ans ;
	int now ;
	int x[N] ;
	int y[N] ;
	int fac[N] ;
	int inv[N] ;
	int pres[N] ;
	int sufs[N] ;
	int expow(int a, int b){
		int res = 1 ;
		a = (a % P + P) % P ;
		while (b){
			if (b & 1)
				res = (ll)res * a % P ;
			a = (ll)a * a % P ; b >>= 1 ;
		}
		return res ;
	}
	int fz[N] ;
	int fm[N] ;
	int tmp[N] ;
	int res[N] ;
	void add(int &a, int b){
		a += b ;
		if (a > P) a -= P ;
	}
	void dec(int &a, int b){
		(a -= b) %= P ;
		if (a < 0) a += P ;
	}
	void fmul(int *t, int deg, int opt){
		for (int i = deg + 1 ; i >= 1 ; -- i)
			tmp[i] = t[i], t[i] = t[i - 1] ;
		for (int i = 1 ; i <= deg + 1 ; ++ i)
			add(t[i], (ll)opt * tmp[i] % P) ;
	}
	void fdiv(int *t, int *ret, int deg, int opt){
		for (int i = 1 ; i <= deg ; ++ i) tmp[i] = t[i] ;
		for (int i = deg - 1 ; i >= 1 ; -- i)
			ret[i] = tmp[i + 1], dec(tmp[i], (ll)tmp[i + 1] * opt % P) ;
	}
	void get_xs(int n){
		fz[1] = 1 ;
		for (int i = 1 ; i <= n ; ++ i)
			fmul(fz, i, (-x[i] + P) % P) ;
		for (int i = 1 ; i <= n ; ++ i){
			int fenmu = 1 ;
			for (int j = 1 ; j <= n ; ++ j)
				if (i != j) fenmu = (ll)fenmu * (x[i] - x[j] + P) % P ;
			fdiv(fz, fm, n + 1, -x[i]) ;
			fenmu = (ll)y[i] * expow(fenmu, P - 2) % P ;
			for (int j = 1 ; j <= n ; ++ j)
				add(res[j], (ll)fenmu * fm[j] % P) ;
		}
	}
	void pre_do(int U){
		fac[0] = 1 ;
		for (int i = 1 ; i <= U ; ++ i)
			fac[i] = (ll)fac[i - 1] * i % P ;
		inv[U] = expow(fac[U], P - 2) ;
		for (int i = U ; i >= 1 ; -- i)
			inv[i - 1] = (ll)inv[i] * i % P ;
	}
	int evenmark(int x){
		return (x & 1) ? -1 : 1 ;
	}
	void get_dnx(int n, int k, bool m){
		if (m){
			pre_do(n) ;
			pres[0] = 1, sufs[n + 1] = 1 ;
			for (int i = 1 ; i <= n ; ++ i)
				pres[i] = ((ll)pres[i - 1] * (k - x[i]) % P + P) % P ;
			for (int i = n ; i >= 1 ; -- i)
				sufs[i] = ((ll)sufs[i + 1] * (k - x[i]) % P + P) % P ;
			for (int i = 1 ; i <= n ; ++ i){
				now = (ll)pres[i - 1] * sufs[i + 1] % P ;
				now = (ll)now * expow((ll)fac[i - 1] * fac[n - i] % P, P - 2) % P ;
				now = (ll)evenmark(n - i) * y[i] % P * now % P ; ans = (ll)(ans + now) % P ;
			}
		}
		else {
			int inow = 1 ;
			pres[0] = 1, sufs[n + 1] = 1 ;
			for (int i = 1 ; i <= n ; ++ i)
				pres[i] = ((ll)pres[i - 1] * (k - x[i]) % P + P) % P ;
			for (int i = n ; i >= 1 ; -- i)
				sufs[i] = ((ll)sufs[i + 1] * (k - x[i]) % P + P) % P ;
			for (int i = 1 ; i <= n ; ++ i){
				inow = 1, now = (ll)pres[i - 1] * sufs[i + 1] % P ;
				for (int j = 1 ; j <= n ; ++ j)
					if (i != j) inow = (ll)inow * ((x[i] - x[j]) % P + P) % P ;
				ans = (ans + (ll)now * expow(inow, P - 2) % P * y[i] % P) % P ;
			}
		}
	}
}
using namespace Interpolation;
void Lagrange(){
	for(int i=1;i<=m+1;++i)Interpolation::x[i]=i-1,Interpolation::y[i]=a[i-1];
	get_xs(m+1);
	for(int i=0;i<=m;++i)a[i]=Interpolation::res[i+1]%mod;
}
int main(){
	freopen("in.txt","r",stdin);
	s[0][0]=1;
	for(int i=1;i<=8000;++i)
		for(int j=1;j<=i;++j)
			s[i][j]=Add(s[i-1][j-1],Mul(j,s[i-1][j]));
	low[0]=1;
	n=read();m=read();xx=read();xx%=mod;n%=mod;
	int inv2=qpow(1-xx+mod,mod-2);
	if(inv2==0)inv2=1;
	for(int i=1;i<=m;++i)low[i]=Mul(low[i-1],n-i+1);
	for(int i=0;i<=m;++i)a[i]=read();
	Lagrange();
	int ans=0;
	for(int i=0;i<=m;++i){
		int res=0;
		for(int j=0;j<=i;++j)res=Add(res,Mul(low[j],Mul(s[i][j],Mul(qpow(Mul(xx,inv2),j),qpow(inv2,Dec(n,j))))));
		ans=Add(ans,Mul(a[i],res));
	}
	int val=1-xx+mod;
	val%=mod;
	if(val==0)val=1;
	ans=Mul(ans,qpow(val,n));
	printf("%d
",ans);
	return 0;
}
原文地址:https://www.cnblogs.com/h-lka/p/15366839.html