题目链接:http://zhengruioi.com/problem/607
题意:
求
∑
j
=
1
i
F
(
j
,
i
)
\sum_{j=1}^{i} F(j, i)
j=1∑iF(j,i)
其中
F
(
l
,
r
)
F(l,r)
F(l,r)为
l
l
l到
r
r
r内所有数字之和的
k
k
k次方,T组询问
n
≤
1
0
5
;
k
≤
100
;
T
≤
5
n \le 10^5; k\le 100; T\le 5
n≤105;k≤100;T≤5
题解:
利用Stirling数降幂:
x
k
=
∑
i
=
0
k
∗
C
(
x
,
i
)
∗
i
!
∗
S
(
k
,
i
)
x^k=\sum_{i=0}^k * C(x,i) * i! * S(k,i)
xk=i=0∑k∗C(x,i)∗i!∗S(k,i)
考虑新加一个数
a
a
a,则:
(
x
+
a
)
k
=
∑
i
=
0
k
∗
C
(
x
+
a
,
i
)
∗
i
!
∗
S
(
k
,
i
)
(x+a)^k=\sum_{i=0}^k * C(x+a,i) * i! * S(k,i)
(x+a)k=i=0∑k∗C(x+a,i)∗i!∗S(k,i)
显然只有组合数一项变了,而
C
(
x
,
i
)
=
C
(
x
−
1
,
i
)
+
C
(
x
−
1
,
i
−
1
)
C(x,i)=C(x-1,i)+C(x-1,i-1)
C(x,i)=C(x−1,i)+C(x−1,i−1),所以我们直接考虑每次加一个组合数:
C
(
x
,
i
)
+
C
(
x
,
i
−
1
)
=
C
(
x
+
1
,
i
)
C(x,i) + C(x,i-1) = C(x+1,i)
C(x,i)+C(x,i−1)=C(x+1,i)
⋯
\cdots
⋯
C
(
x
+
a
−
1
,
i
)
+
C
(
x
+
a
−
1
,
i
−
1
)
=
C
(
x
+
a
,
i
)
C(x+a-1,i)+C(x+a-1,i-1)=C(x+a,i)
C(x+a−1,i)+C(x+a−1,i−1)=C(x+a,i)
每次维护一下前缀和即可
代码:
// by Balloons
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define mpr make_pair
#define debug() puts("okkkkkkkk")
#define rep(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
using namespace std;
typedef long long LL;
const int inf = 1 << 30;
const int maxn=470005,mod=1e9+7;
int pw(int x,int y){
if(!y)return 1;
if(y==1)return x%mod;
int mid=pw(x,y>>1);
if(y&1)return 1ll*mid*mid%mod*x%mod;
return 1ll*mid*mid%mod;
}
int n,k;
char s[maxn];
int pre[maxn];
int fac[maxn],inv[maxn];
int S[110][110];
int ad[maxn];
int ans[maxn];
int C[110][110];
void solve(){
for(int i=1;i<=n;i++){ // pre[i] 考虑到当前的位置,计算答案时需要的为 i
int tmp=s[i]-'0';int prex=tmp;
while(tmp>=1){ // (x)^k --> (x+a)^k
for(int j=k;j>=1;j--) // 前缀和 C(x-1,i)+C(x-1,i-1) = C(x,i)
(pre[j] += pre[j-1])%=mod;
-- tmp;
}
for(int j=0;j<=k;j++)
(pre[j]+=C[prex][j])%=mod;
int res=0;
for(int j=0;j<=k;j++){
// pre[i] -- C(x+a,i)
(res += 1ll * S[k][j] * fac[j] % mod * pre[j] % mod)%=mod;
}
printf("%d ",res);
}
puts("");
}
int main(){
int te;scanf("%d",&te);
fac[0]=1;
for(int i=1;i<=105;i++)fac[i]=1ll*fac[i-1]*i%mod;
C[0][0]=1;
for(int i=1;i<=105;i++){
C[i][0]=C[i][i]=1;
for(int j=1;j<i;j++)C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod;
}
S[0][0]=1;
for(int i=1;i<=105;i++){
for(int j=1;j<=105;j++)S[i][j]=(S[i-1][j-1]+1ll*S[i-1][j]*j%mod)%mod;
}
while(te--){
scanf("%d%d",&n,&k);
scanf("%s",s+1);
memset(pre,0,sizeof pre);
solve();
}
return 0;
}