【题解】【清华集训2016】如何优雅地求和
\(\text{Solution:}\)
\[\sum_{k=0}^n f(k)\binom{n}{k}x^k (1-x)^{n-k}
\\
=\sum_{j=0}^m a_j\sum_{k=0}^n k^i \binom{n}{k}x^k (1-x)^{n-k}
\\
=\sum_{i=0}^m a_i\sum_{k=0}^n \sum_{j=0}^k \binom{k}{j}j!{i\brace j}\binom{n}{k}x^k (1-x)^{n-k}
\\
=\sum_{i=0}^m a_i\sum_{k=0}^n \sum_{j=0}^k j!{i\brace j}\binom{n}{j}\binom{n-j}{k-j}x^k (1-x)^{n-k}
\\
=\sum_{i=0}^m a_i\sum_{k=0}^n \sum_{j=0}^k n^{\underline{j}}{i\brace j}\binom{n-j}{k-j}x^k (1-x)^{n-k}
\\
=\sum_{i=0}^m a_i\sum_{j=0}^n n^{\underline{j}}{i\brace j} \sum_{k=j}^n \binom{n-j}{k-j}x^k (1-x)^{n-k}
\\
=\sum_{i=0}^m a_i\sum_{j=0}^n n^{\underline{j}}{i\brace j} \sum_{k=0}^{n-j} \binom{n-j}{k}x^{k+j} (1-x)^{n-k-j}
\\
=\sum_{i=0}^m a_i\sum_{j=0}^n n^{\underline{j}}{i\brace j} \left(\frac{1-x}{x}\right)^{-j} \sum_{k=0}^{n-j} \binom{n-j}{k}x^{k} (1-x)^{n-k}
\\
=\sum_{i=0}^m a_i\sum_{j=0}^n n^{\underline{j}}{i\brace j} \left(\frac{1-x}{x}\right)^{-j} (1-x)^n \sum_{k=0}^{n-j} \binom{n-j}{k}\left(\frac{x}{1-x}\right)^k
\\
=\sum_{i=0}^m a_i\sum_{j=0}^n n^{\underline{j}}{i\brace j} \left(\frac{1-x}{x}\right)^{-j} (1-x)^n \left(\frac{1}{1-x}\right)^{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\n",ans);
return 0;
}