题意:
分析:
- 前置芝士:第二类斯特林数
首先先写出第二类斯特林数将普通幂转化为下降幂的式子:
(displaystyle i^k=sum_{j=0}^kS_k^jfrac{i!}{(i-j)!})
然后开始大力推柿子
[sum_{i=1}^nC_n^i i^k
\
=sum_{i=1}^nC_n^isum_{j=0}^kS_k^jfrac{i!}{(i-j)!}
\
=sum_{i=1}^nC_n^isum_{j=0}^kj!S_k^jC_i^j
\
=sum_{j=0}^kj!S_k^jsum_{i=1}^nfrac{n!i!}{(n-i)!i!(i-j)!j!}
]
关键的一步来了,我们发现原来的瓶颈在于组合数的处理,所以我们要考虑优化组合数的计算,把两项组合数混在一起重新组合
[=sum_{j=0}^kj!S_k^jsum_{i=1}^nfrac{n!(n-j)!}{(n-i)!(n-j)!(i-j)!j!}
\
=sum_{j=0}^kj!S_k^jsum_{i=1}^nfrac{n!}{(n-j)!j!}frac{(n-j)!}{(n-i)!(i-j)!}
\
=sum_{j=0}^kj!S_k^jsum_{i=1}^nC_n^jC_{n-j}^{i-j}
\
=sum_{j=0}^kj!S_k^jC_n^jsum_{i=j}^nC_{n-j}^{i-j}
\
=sum_{j=0}^kj!S_k^jC_n^j2^{n-j}
\
=sum_{j=0}^kfrac{n!}{(n-j)!}S_k^j2^{n-j}
]
然后我们可以 (O(k^2)) 预处理出所有我们需要的东西
- 另解:
其实算到这里已经可以 A 掉这道题了,但是其实还是有一些更优的办法,比如说我们预处理 Strling 数的复杂度是 (O(k^2)) ,但是第二类斯特林数有一个通项公式 (displaystyle S_k^n=sum_{i=0}^nfrac{(-1)^i}{i!}frac{(n-i)^k}{(n-i)!}),这是一个卷积的形式可以用 NTT 优化到 (O(nlog)) 但是这个题模数不对劲/kk
代码:
#include<bits/stdc++.h>
#define inl inline
#define reg register
using namespace std;
namespace zzc
{
typedef long long ll;
const ll maxn = 5005;
const ll mod = 1e9+7;
ll s[maxn][maxn];
ll n,k,ans=0;
ll qpow(ll x,ll y)
{
ll res=1;
while(y)
{
if(y&1) res=res*x%mod;
x=x*x%mod;
y>>=1;
}
return res;
}
void init()
{
s[0][0]=1;
for(int i=1;i<=5000;i++)
{
for(int j=1;j<=i;j++)
{
s[i][j]=(s[i-1][j-1]+s[i-1][j]*j%mod)%mod;
}
}
}
void work()
{
init();
scanf("%lld%lld",&n,&k);
ll fac=1,pw=qpow(2,n);
for(ll j=0;j<=k;j++)
{
ans=(ans+fac*s[k][j]%mod*pw%mod)%mod;
fac=fac*(n-j)%mod;
pw=pw*qpow(2,mod-2)%mod;
}
printf("%lld
",ans);
}
}
int main()
{
zzc::work();
return 0;
}