题解
以后看到幂和并且幂次比较小的时候尽量往斯特林数方面想
关于题解,有一个巧妙的巧妙的实现就是把 i!乘进组合数
接下来就只需要维护每个值+1之后的下降k次幂之和(把k取0~100的下降幂之和都要动态维护)
想了我好久。。。
后来看到了标程,就一句话f[i][k]=f[i-1][k-1]*i+f[i-1][k],妙啊!!!!
展开一下,发现每个数的下降k-1次幂都可以提出来,相当于给最后一个数加上i
而最后一个数加上i就刚好使k次下降幂变成了k+1次下降幂
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 105
const int mod=1000000007;
int S[N][N],f[N];
char ch[50005];
int main()
{
freopen("number.in","r",stdin);
freopen("number.out","w",stdout);
int T,n,k,i,j,ans=0;
scanf("%d",&T);
for(i=1;i<=100;i++){
S[i][1]=S[i][i]=1;
for(j=2;j<i;j++)
S[i][j]=(1ll*S[i-1][j]*j+1ll*S[i-1][j-1])%mod;
}
while(T--){
memset(f,0,sizeof(f));
scanf("%d%d%s",&n,&k,ch+1);
for(i=1;i<=n;i++){
ans=0;
f[0]++;if(f[0]>=mod)f[0]-=mod;
while(ch[i]-->'0')
for(j=k;j>=1;j--)
f[j]=(1ll*f[j]+1ll*f[j-1]*j)%mod;// miao a
for(j=0;j<=k;j++)
ans=(1ll*ans+1ll*S[k][j]*f[j])%mod;
printf("%d",ans);
if(i<n)printf(" ");
}
printf("\n");
}
}