求
∑ k = 0 n f ( k ) × x k × ( n k ) ( m o d p ) \sum_{k=0}^n f(k) \times x^k \times \binom{n}{k} \pmod p k=0∑nf(k)×xk×(kn)(modp)
其中 n , x , p n,x,p n,x,p 为给定整数, f ( k ) f(k) f(k) 为给定多项式 f ( k ) = ∑ i = 0 m a i k i f(k)=\sum_{i=0}^m a_ik^i f(k)=∑i=0maiki 。
n , x , p , a i ≤ 1 0 9 , m ≤ min ( n , 1000 ) n,x,p,a_i \le 10^9,\ \ m \le \min(n,1000) n,x,p,ai≤109, m≤min(n,1000)
1s
\\
\\
\\
转了一圈,这题的推法似乎多种多样啊。。。(虽然本质相同
就记录一个我觉得比较好的吧。
核心思路就是 k i ( n k ) k^i\binom{n}{k} ki(kn) 写成下降幂多项式,然后发现有奇效。
设 f ( k ) = ∑ i = 0 m a i k i f(k)=\sum_{i=0}^m a_ik^i f(k)=∑i=0maiki 转化成下降幂多项式为
f ( k ) = ∑ i = 0 m b i k i ‾ = ∑ i = 0 m b i k ! ( k − i ) ! f(k)=\sum_{i=0}^m b_i k^{\underline i} = \sum_{i=0}^m b_i \frac{k!}{(k-i)!} f(k)=i=0∑mbiki=i=0∑mbi(k−i)!k!
代入原式有
∑ k = 0 n f ( k ) × x k × ( n k ) = ∑ k = 0 n ∑ i = 0 m b i k ! ( k − i ) ! × x k × n ! k ! ( n − k ) ! = ∑ k = 0 n ∑ i = 0 m b i × x k × n ! ( n − k ) ! ( k − i ) ! = ∑ k = 0 n ∑ i = 0 m b i n ! ( n − i ) ! × x k × ( n − i n − k ) = ∑ i = 0 m b i n ! ( n − i ) ! ∑ k = 0 i x k ( n − i n − k ) = ∑ i = 0 m b i n i ‾ ( x + 1 ) n − i \begin{aligned} \sum_{k=0}^n f(k) \times x^k \times \binom{n}{k} &= \sum_{k=0}^n\sum_{i=0}^m b_i \frac{k!}{(k-i)!} \times x^k \times \frac{n!}{k!(n-k)!} \\ &= \sum_{k=0}^n\sum_{i=0}^m b_i \times x^k \times \frac{n!}{(n-k)!(k-i)!} \\ &= \sum_{k=0}^n\sum_{i=0}^m b_i \frac{n!}{(n-i)!} \times x^k \times \binom{n-i}{n-k} \\ &= \sum_{i=0}^m b_i \frac{n!}{(n-i)!} \sum_{k=0}^i x^k \binom{n-i}{n-k} \\ &= \sum_{i=0}^m b_i n^{\underline i} (x+1)^{n-i} \end{aligned} k=0∑nf(k)×xk×(kn)=k=0∑ni=0∑mbi(k−i)!k!×xk×k!(n−k)!n!=k=0∑ni=0∑mbi×xk×(n−k)!(k−i)!n!=k=0∑ni=0∑mbi(n−i)!n!×xk×(n−kn−i)=i=0∑mbi(n−i)!n!k=0∑ixk(n−kn−i)=i=0∑mbini(x+1)n−i
这个东西 O ( m ) O(m) O(m) 循环一遍就好了, ( x + 1 ) n − i (x+1)^{n-i} (x+1)n−i 可以预处理也可以快速幂。
至于 b i b_i bi 的求法,也就是多项式转下降幂多项式,根据
x i = ∑ j = 0 i S ( i , j ) x j ‾ x^i = \sum_{j=0}^i S(i,j) x^{\underline j} xi=j=0∑iS(i,j)xj
(其中 S ( i , j ) S(i,j) S(i,j) 表示第二类斯特林数)可得
∑ i = 0 m a i x i = ∑ i = 0 m a i ∑ j = 0 i S ( i , j ) x j ‾ = ∑ j = 0 x j ‾ ∑ i = j m a i S ( i , j ) \begin{aligned} \sum_{i=0}^m a_ix^i &= \sum_{i=0}^m a_i \sum_{j=0}^i S(i,j) x^{\underline j} \\ &= \sum_{j=0} x^{\underline j} \sum_{i=j}^m a_i S(i,j) \end{aligned} i=0∑maixi=i=0∑maij=0∑iS(i,j)xj=j=0∑xji=j∑maiS(i,j)
因此预处理第二类斯特林数,然后 b j = ∑ i = j m a i S ( i , j ) b_j= \sum_{i=j}^m a_iS(i,j) bj=∑i=jmaiS(i,j) 即可。
#include
#define fo(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
typedef long long LL;
const int maxm=1005;
LL n,x,mo,a[maxm];
int m;
LL S[maxm][maxm];
void S_pre(int n)
{
fo(i,0,m)
{
fo(j,1,i-1) S[i][j]=(S[i-1][j-1]+j*S[i-1][j])%mo;
S[i][i]=1;
}
}
LL b[maxm];
void FFP()
{
fo(i,0,m)
fo(j,i,m) (b[i]+=a[j]*S[j][i])%=mo;
}
LL Pow(LL x,LL y)
{
LL re=1;
for(; y; y>>=1, x=x*x%mo) if (y&1) re=re*x%mo;
return re;
}
int main()
{
freopen("problem.in","r",stdin);
freopen("problem.out","w",stdout);
scanf("%lld %lld %lld %d",&n,&x,&mo,&m);
fo(i,0,m) scanf("%lld",&a[i]);
S_pre(m);
FFP();
LL ndown=1, xpow=1, ans=0;
fo(i,0,m)
{
(ans+=b[i]*xpow%mo*ndown%mo*Pow(x+1,n-i))%=mo;
(xpow*=x)%=mo;
(ndown*=n-i)%=mo;
}
printf("%lld\n",ans);
}