题意:给你一个只由0~9字符构成的长度为n(n<=50000)的字符串a,
定义,求对于每个i(i=1,2,...,n) ,输出。答案对1e9+7取模。
由题意,存在表达式
令s[i]为a[i]的前缀和,再进行二项式展开,则有
因此
组合数可以O(k^2)预处理,s[i]可以O(n)预处理,s[i]^k可以O(n*k)预处理,s[i]^k的前缀和也可以O(n*k)预处理,对于每个i,O(k)计算ans[i],总复杂度为O(n*k)
代码:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll mo=1e9+7;
const int maxn=50010;
ll s[maxn],ss[maxn][101],sss[maxn][101];
ll c[101][101],n,k;
char a[maxn];
void init()
{
for(int i=0;i<=100;i++)
{
c[i][0]=1;
for(int j=1;j<=i;j++)
{
c[i][j]=(c[i-1][j]+c[i-1][j-1])%mo;
}
}
}
int main()
{
init();
int T,cas=1;
scanf("%d",&T);
while(T--)
{
scanf("%lld%lld",&n,&k);
getchar();
scanf("%s",a+1);
s[0]=0;
for(ll i=1;i<=n;i++)
{
s[i]=s[i-1]+(a[i]&15);
}
for(ll i=1;i<=n;i++)
{
ss[i][0]=1;
sss[i][0]=0;
for(ll j=1;j<=k;j++)
{
ss[i][j]=(ss[i][j-1]*s[i])%mo;
sss[i][j]=(sss[i-1][j]+ss[i][j])%mo;
}
}
for(ll i=1;i<=n;i++)
{
ll ans=i*c[k][0]%mo*ss[i][k]%mo;
ll tmp;
for(ll j=1;j<=k;j++)
{
if(j&1) tmp=-sss[i-1][j];
else tmp=sss[i-1][j];
ans=(ans+(c[k][j]*ss[i][k-j]%mo*tmp)%mo)%mo;
}
ans=(ans+mo)%mo;
printf("%lld%c",ans,i==n?'\n':' ');
}
}
return 0;
}