屑题,估计考场上遇见这种东西我会直接被送退役。(悲)
这一题可以当做下降幂多项式入门。
下降幂记作 \(n^{\underline x}=\frac{n!}{(n-x)!}\)。
这个东西也有一个你小学就知道的名字叫做排列。
推式子的基础是 \(k^{\underline m}\dbinom n k=\frac{k!n!}{(k-m)!k!(n-k)!}=\frac{n!}{(k-m)!(n-k)!}=\frac{n!(n-m)!}{(k-m)!(n-k)!(n-m)!}=\dbinom{n-m}{k-m}n^{\underline m}\),\(x^n=\sum_{i=0}^n{n\brace i}x^{\underline i}\) 和二项式定理 \((x+y)^n=\sum_{i=0}^n\dbinom n ix^iy^{n-i}\)。
我们开始:
\(\sum_{k=0}^n\sum_{i=0}^ma_ik^ix^k\dbinom n k\)
\(=a_0\sum_{p=0}^n\dbinom n px^p\sum_{k=0}^n(\sum_{i=1}^mk^{\underline i}\sum_{j=i}^ma_j{j\brace i}\dbinom n kx^k)\)
\(=a_0(x+1)^n+\sum_{i=1}^m(\sum_{j=i}^ma_j{j\brace i})n^{\underline i}\sum_{k=0}^n\dbinom{n-i}{k-i}x^k\)
\(=a_0(x+1)^n+\sum_{i=1}^m(\sum_{j=i}^ma_j{j\brace i})n^{\underline i}\sum_{k=0}^{n-i}\dbinom{n-i}{k}x^{k+i}\)
\(=a_0(x+1)^n+\sum_{i=1}^m(\sum_{j=i}^ma_j{j\brace i})n^{\underline i}x^i\sum_{k=0}^{n-i}\dbinom{n-i}{k}x^k\)
\(=a_0(x+1)^n+\sum_{i=1}^m(\sum_{j=i}^ma_j{j\brace i})n^{\underline i}x^i(x+1)^{n-i}\)
其中把多项式的常数项拆出来单算的原因是斯特林数 \(n\brace m\) 中 \(n,m\) 是正整数。
然后 \(O(m^2)\) 预处理第二类斯特林数,再每次 \(O(m^2)\) 大力计算这个式子即可。
#include<iostream>
#include<cstdio>
using namespace std;
#define int long long
int s[1001][1001],n,m,x,mod,ans,a[1001],c,sum;
inline int pw(int a,int b)
{
int res=1;
while(b)
{
if(b&1)
res=res*a%mod;
b>>=1;
a=a*a%mod;
}
return res;
}
signed main()
{
scanf("%lld%lld%lld%lld",&n,&x,&mod,&m);
x%=mod;
for(register int i=0;i<=m;++i)
scanf("%lld",&a[i]);
s[1][1]=1;
for(register int i=2;i<=m;++i)
for(register int j=1;j<=i;++j)
s[i][j]=(j*s[i-1][j]%mod+s[i-1][j-1])%mod;
ans=a[0]*pw((x+1)%mod,n)%mod;
c=1;
for(register int i=1;i<=m;++i)
{
c=c*(n-i+1)%mod*x%mod;
sum=0;
for(register int j=i;j<=m;++j)
sum=(sum+a[j]*s[j][i]%mod)%mod;
ans=(ans+pw((x+1)%mod,n-i)*c%mod*sum%mod)%mod;
}
printf("%lld\n",ans);
return 0;
}