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;
}
posted @ 2026-01-26 15:32  OTn53_qwq  阅读(4)  评论(0)    收藏  举报