题目链接:https://vjudge.net/problem/HihoCoder-1430
转自:https://www.cnblogs.com/Simon-X/p/6146733.html
题意:有一串数字序列,F(j,i)=(
∑
l
=
j
i
s
[
l
]
\displaystyle \sum^{i}_{l=j}s[l]
l=j∑is[l])^k,其中是s[l]代表第l位上的数字,下标从1开始。求(
∑
j
=
1
i
F
(
j
,
i
)
\displaystyle \sum^{i}_{j=1}F(j,i)
j=1∑iF(j,i))。
比如第一组样例 5 1 12345 第一项=1,第二项=
(
1
+
2
)
1
(1+2)^1
(1+2)1+
2
1
2^1
21=5,第三项=
(
1
+
2
+
3
)
1
(1+2+3)^1
(1+2+3)1+
(
2
+
3
)
1
(2+3)^1
(2+3)1+
3
1
3^1
31=14
思路:算了一下暴力是过不去的。但是可以用二项式定理来化简。如果是加法
不好表示。但是如果是减法
#include <bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
long long c[110][110],s[50010][110],ss[50010][110];
void init()
{
for(int i=0; i<=105; i++)
{
c[i][0]=1;
c[i][1]=i;
}
for(int i=1; i<=105; i++)
{
for(int j=2; j<=i; j++)
{
c[i][j]=(c[i-1][j]+c[i-1][j-1])%mod;
}
}
}
int T,n,k;
char rd[50010];
int main()
{
init();
for(int i=0;i<50005;i++)
{
s[i][0]=ss[i][0]=1;//初始化0次方为1
}
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&k);
getchar();
scanf("%s",rd);
for(int i=0;i<n;i++)
{
s[i+1][1]=rd[i]-'0';
}
for(int i=1;i<=n;i++)
{
s[i][1]=(s[i][1]+s[i-1][1])%mod;//计算前缀和
for(int j=2;j<=k;j++)
{
s[i][j]=(s[i][j-1]*s[i][1])%mod;//前缀和的k次方
}
}
for(int i=1;i<=n;i++)
{
for(int j=0;j<=k;j++)
{
ss[i][j]=(s[i][j]+ss[i-1][j])%mod;
}
}
for(int i=1;i<=n;i++)
{
if(i>1)
printf(" ");
long long ans=0;
for(int j=0;j<=k;j++)
{
long long t=(c[k][j]*s[i][j])%mod;
if((k-j)&1)//如果是奇数次幂 负号不能被抵消
{
ans=ans-(t*ss[i-1][k-j])%mod;
}
else
{
ans=ans+(t*ss[i-1][k-j])%mod;
}
ans%=mod;
}
printf("%lld",(ans+mod)%mod);
}
printf("\n");
}
}