「CF932E」Team Work
problem
Solution
题意:求∑i=1n(ni)×ik
大力颓柿子,根据常幂转下降幂公式,有
i=1∑n(ni)×ik
=i=1∑n(ni)j=0∑i{kj}×ij
=i=1∑n(ni)j=0∑i{kj}×j!(ij)
=j=0∑min(n,k){kj}i=j∑ni!(n−i)!n!×j!×j!(i−j)!i!
=j=0∑min(n,k){kj}i=j∑n(n−i)!n!×(i−j)!1
后面那个求和上下同乘(n−j)!,有
j=0∑min(n,k){kj}i=j∑n(n−i)!n!×(i−j)1×(n−j)!(n−j)!
=j=0∑min(n,k){kj}(n−j)!n!i=j∑n(n−jn−i)
i<j的时候组合数为0,不妨把i的下界变为0,于是有
j=0∑min(n,k){kj}(n−j)!n!i=0∑n(n−jn−i)
=j=0∑min(n,k){kj}(n−j)!n!×2n−j
于是我们可以O(k2)递推求出第二类斯特林数,枚举j时迭代计算(n−j)!n!,快速幂计算2n−j即可
Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| #include <cstdio> #include <algorithm> #include <cstdlib> #include <cstring> #include <cmath> #include <iostream> #define inv(x) (fastpow((x),mod-2)) using namespace std; typedef long long ll;
template <typename T> void read (T &t) { t=0;int f=0;char c=getchar(); while(!isdigit(c)){f|=c=='-';c=getchar();} while(isdigit(c)){t=t*10+c-'0';c=getchar();} if(f)t=-t; }
const int maxk=5000+5; const ll mod=1e9+7;
ll n,k; ll s[maxk][maxk];
ll fastpow(ll a,ll b) { ll re=1,base=a; while(b) { if(b&1) re=re*base%mod; base=base*base%mod; b>>=1; } return re; }
int main() { read(n),read(k); s[0][0]=1; for(register ll i=1;i<=k;++i) for(register ll j=1;j<=i;++j) s[i][j]=(s[i-1][j-1]+j*s[i-1][j]%mod)%mod; ll kkk=1,ans=0; for(register ll j=0;j<=min(n,k);++j) { ans=(ans+s[k][j]*kkk%mod*fastpow(2,n-j)%mod)%mod; kkk=kkk*(n-j)%mod; } printf("%lld",ans); return 0; }
|