题目大意
求
∑
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
=
i
n
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=i}^n 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=i∑nxk(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<bits/stdc++.h>
#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);
}