题解

以后看到幂和并且幂次比较小的时候尽量往斯特林数方面想

关于题解,有一个巧妙的巧妙的实现就是把 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");
	}
}