P6620 [省选联考 2020 A 卷] 组合数问题 / 上升下降普通幂转换
题目传送门:P6620 [省选联考 2020 A 卷] 组合数问题。
有关上升下降普通幂转换的四个公式:
\[x^{\underline{n}} = \sum_{k=0}^n (-1)^{n-k} {n \brack k} x^k
\]
\[x^n = \sum_{k=0}^n {n \brace k} x^{\underline{k}}
\]
\[x^{\overline{n}} = \sum_{k=0}^n {n \brack k} x^k
\]
\[x^n=\sum_{k=0}^n (-1)^{n-k} {n \brace k} x^{\overline{k}}
\]
下降幂与组合数有关的公式:
\[{n\choose k} k^{\underline{m}} = {n-m\choose k-m} n^{\underline{m}}
\]
知道这两个就可以做这题了。
考虑将 \(f(x)\) 转化为下降幂多项式 \(f(x)=\sum\limits_{i=0}^m b_ix^{\underline{i}}\)。
然后就是推式子:
\[\begin{aligned}
ans&=\sum_{k=0}^n \sum_{i=0}^m b_i k^{\underline{i}}x^k {n\choose k} \\
&=\sum_{k=0}^n \sum_{i=0}^m b_i {n-i\choose k-i}n^{\underline{i}} x^k \\
&=\sum_{i=0}^m b_i n^{\underline{i}} \sum_{k=0}^n {n-i\choose k-i} x^k \\
&=\sum_{i=0}^m b_i n^{\underline{i}} \sum_{k=0}^{n-i} {n-i\choose k} x^{k+i} \\
&=\sum_{i=0}^m b_i n^{\underline{i}} x^i \sum_{k=0}^{n-i} {n-i\choose k} x^k \\
&=\sum_{i=0}^m b_i n^{\underline{i}} x^i (x+1)^{n-i}
\end{aligned}\]
至于 \(b\) 怎么求,直接利用 \(x^n = \sum\limits_{k=0}^n {n \brace k} x^{\underline{k}}\) 即可。
#include<bits/stdc++.h>
#define int long long
#define double long double
using namespace std;
inline int read(){
char c=getchar();
int f=1,ans=0;
while(c<48||c>57) f=(c==45?f=-1:1),c=getchar();
while(c>=48&&c<=57) ans=(ans<<1)+(ans<<3)+(c^48),c=getchar();
return ans*f;
}
const int N=1010;
int n,x,mod,m,s[N][N],a[N],b[N];
inline int qpow(int a,int b){
int s=1;
while(b){if (b&1) s=s*a%mod;a=a*a%mod;b>>=1;}
return s;
}
int f[N];
main(){
n=read(),x=read(),mod=read(),m=read();
f[0]=1;
for (int i=1;i<=m;i++) f[i]=f[i-1]*(n-i+1)%mod;
s[0][0]=1;
for (int i=1;i<=m;i++) for (int j=1;j<=m;j++) s[i][j]=(s[i-1][j]*j%mod+s[i-1][j-1])%mod;
for (int i=0;i<=m;i++) a[i]=read();
for (int i=0;i<=m;i++) for (int j=0;j<=i;j++) b[j]=(b[j]+s[i][j]*a[i]%mod)%mod;
int ans=0;
for (int i=0;i<=m;i++) ans=(ans+b[i]*f[i]%mod*qpow(x,i)%mod*qpow(x+1,n-i)%mod)%mod;
cout <<ans;
return 0;
}

浙公网安备 33010602011771号