Luogu6620 [省选联考 2020 A 卷] 组合数问题
Luogu6620 [省选联考 2020 A 卷] 组合数问题
数学蒟蒻再一次一败涂地。。。
我们知道:
\[{n \choose k}k^{\underline{m}}={n-m \choose k-m}n^{\underline{m}}
\]
将\(f(x)\)转下降幂,得\(f(x)=\sum_{i=0}^m b_i x^{\underline{i}}\)。
\[\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 x^k {n-i \choose k-i} n^{\underline{i}}\\
=\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_{k=0}^{n-i} {n-i \choose k} x^k\\
=\sum_{k=0}^{n-i} {n-i \choose k} x^k 1^{n-i-k}\\
=(x+1)^{n-i}
\]
巨大的\(n\)就这么没了。。。
剩下一步就是普通幂转下降幂。
\[x^{\underline n}=\sum_{i=0}^n (-1)^{n-i} {n \brack i} x^i\\
a_i=\sum_{j=i}^n (-1)^{j-i} {j \brack i} b_j
\]
一步斯特林反演:
\[b_i=\sum_{j=i}^n {j \brace i} a_i
\]
\(O(m^2)\)求出第二类斯特林数,这道题就做完了。
\(Code:\)
#include<iostream>
#include<cstdio>
#include<algorithm>
#define N 1005
#define ll long long
using namespace std;
int n,x,p,m,a[N],b[N];
int ans=0,s2[N][N];
void Add(int &x,int y)
{
x=(x+y)%p;
}
void Mul(int &x,int y)
{
x=(ll)x*y%p;
}
int add(int x,int y)
{
return (x+y)%p;
}
int mul(int x,int y)
{
return (ll)x*y%p;
}
int ksm(int x,int y)
{
int ans=1;
while (y)
{
if (y & 1)
Mul(ans,x);
Mul(x,x);
y >>=1;
}
return ans;
}
int main()
{
scanf("%d%d%d%d",&n,&x,&p,&m);
for (int i=0;i<=m;++i)
scanf("%d",&a[i]);
s2[0][0]=1;
for (int i=1;i<=m;++i)
for (int j=1;j<=i;++j)
s2[i][j]=add(s2[i-1][j-1],mul(s2[i-1][j],j));
for (int i=0;i<=m;++i)
for (int j=i;j<=m;++j)
Add(b[i],mul(s2[j][i],a[j]));
int xs=1,xj=1;
for (int i=0;i<=m;++i)
{
Add(ans,mul(b[i],mul(xj,mul(xs,ksm(x+1,n-i)))));
Mul(xs,x),Mul(xj,n-i);
}
ans=(ans%p+p)%p;
printf("%d\n",ans);
return 0;
}