20210524 刷题赛 乐队_题解【另一种思路】
20210524 刷题赛 乐队_题解【另一种思路】
题解给的做法是第二类斯特林数通常幂转下降幂,其实更简单的也可以直接转成牛顿级数。
把
F
(
x
)
F(x)
F(x) 写成牛顿级数
F
(
x
)
=
∑
j
=
0
k
c
j
(
x
j
)
F(x)=\sum_{j=0}^k c_j {x\choose j}
F(x)=j=0∑kcj(jx)
目标式子为
∑
i
=
0
n
(
n
i
)
2
n
−
i
F
(
i
)
=
∑
i
=
0
n
∑
j
=
0
k
(
n
i
)
2
n
−
i
c
j
(
i
j
)
=
∑
j
=
0
k
(
n
j
)
c
j
∑
i
=
0
n
2
n
−
i
(
n
−
j
i
−
j
)
=
∑
j
=
0
k
(
n
j
)
c
j
3
n
−
j
\begin{aligned} &\sum_{i=0}^n {n\choose i}2^{n-i}F(i)\\ =&\sum_{i=0}^n \sum_{j=0}^k {n\choose i}2^{n-i}c_j {i\choose j}\\ =&\sum_{j=0}^k {n\choose j}c_j\sum_{i=0}^n 2^{n-i}{n-j\choose i-j}\\ =&\sum_{j=0}^k {n\choose j}c_j3^{n-j} \end{aligned}
===i=0∑n(in)2n−iF(i)i=0∑nj=0∑k(in)2n−icj(ji)j=0∑k(jn)cji=0∑n2n−i(i−jn−j)j=0∑k(jn)cj3n−j
由于我太菜了,在最后一步想了好久,最后发现可以强行给
∑
i
(
a
i
)
2
i
\sum_i{a\choose i} 2^i
∑i(ia)2i 一个组合意义:
现有 a a a 个白球,你选了 i i i 个出来,并给这个 i i i 个球任意涂上红色或蓝色,问有几种涂色方案。这个就等价于现有 a a a 个球,可以给每个球任意涂上白红蓝三种颜色的一种,问方案数。
所以就有了 ∑ i ( a i ) 2 i = 3 a \sum_i{a\choose i} 2^i=3^a ∑i(ia)2i=3a ,这个可以扩展到 ∑ i ( a i ) X i = ( X + 1 ) a \sum_i{a\choose i} X^i=(X+1)^a ∑i(ia)Xi=(X+1)a 。
#include <bits/stdc++.h>
#define K 5003
using namespace std;
typedef long long ll;
const int mod=998244853;
ll n,k,fac[K],inv[K];
ll a[K],A[K][K];
ll ksm(ll x,ll y){
ll res=1;
while(y){
if(y&1) res=res*x%mod;
x=x*x%mod; y>>=1;
}
return res;
}
void init(){
fac[0]=1;
for(int i=1;i<=k;i++) fac[i]=fac[i-1]*i%mod;
inv[k]=ksm(fac[k],mod-2);
for(int i=k-1;i>=0;i--)
inv[i]=inv[i+1]*(i+1)%mod;
}
ll get_A(ll x){
ll res=0,X=1;
for(int i=0;i<=k;i++,X=X*x%mod) res=(res+X*a[i]%mod)%mod;
return res;
}
ll C[K];
int main(){
// freopen("band2.in","r",stdin);
cin>>n>>k;
init();
for(int i=0;i<=k;i++) cin>>a[i],a[i]%=mod;
for(int i=0;i<=k;i++) A[0][i]=get_A(i);
for(int i=k,op=1;i>=1;i--,op++)
for(int j=0;j<=i-1;j++)
A[op][j]=(A[op-1][j+1]-A[op-1][j]+mod)%mod;
for(int i=0;i<=k;i++) a[i]=A[i][0];
C[0]=1;
for(int i=1;i<=k;i++) C[i]=C[i-1]*(n-i+1)%mod;
ll res=0;
for(int i=0;i<=k;i++)
(res+=a[i]*C[i]%mod*inv[i]%mod*ksm(3,n-i)%mod)%=mod;
cout<<res;
}