T3 字符串问题(string)
(WOJ4818)
3.1 题目描述
经过一番斗争以后,高钧终于放弃了抵抗。现在高匀有一个长度为
n
n
n的由数字字符
0
∼
9
0∼9
0∼9组成的字符串,在感受
a
l
b
alb
alb的快乐之前,他有一个最后的问题。
高匀有
k
k
k个加号,他想将这
k
k
k个加号插入到这个字符串中组成一个合法的表达式合法的表达式满足不存在两个连续的加号,且第一个字符和最后一个字符不是加号,比如
1
+
01
,
2
+
35
+
8
1+01,2+35+8
1+01,2+35+8是合法的表达式,而
+
101
,
23
+
58
+
,
23
+
+
58
+101,23+58+,23++58
+101,23+58+,23++58不是,表达式中的数字是十进制的,可以有前导零。
高匀想将所有的不同的合法表达式的值都求出来,表达式的值即为这个表达式进行从左到右的加法运算得到的值,例如表达式
2
+
3
2+3
2+3的值是
5
5
5,表达式
02
+
33
02+33
02+33的值是
35
35
35。两个表达式不同当且仅当这两个表达式的某一位置的字符不同。因为合法的表达式可能很多,所以高匀只想让你告诉他所有不同合法表达式的值之和,由于答案可能很大,你只要告诉他答案对
998244353
998244353
998244353取模的值即可。
3.2 输入输出格式
3.2.1 输入格式
第一行,两个正整数
n
,
k
n,k
n,k,表示字符串长度和加号的数量
第二行一个长度为
n
n
n的字符串,由数字字符
0
∼
9
0∼9
0∼9组成
3.2.2 输出格式
一行一个数,表示答案对
998244353
998244353
998244353取模的结果
3.3 样例
3.3.1 样例1输入
4 2
2333
3.3.2 样例1输出
105
3.3.3 样例1解释
不同的合法表达式有
2
+
3
+
33
,
2
+
33
+
3
,
23
+
3
+
3
2+3+33,2+33+3,23+3+3
2+3+33,2+33+3,23+3+3。
这三个表达式的值分别为
38
,
38
,
29
38,38,29
38,38,29,所以答案为
(
38
+
38
+
29
)
m
o
d
998244353
=
105
(38+38+29)mod998244353 = 105
(38+38+29)mod998244353=105。
3.3.4 样例2输入
4 3
2333
3.3.5 样例2输出
11
3.4 数据范围与提示
对于100%的数据,有
1
≤
n
≤
5
×
1
0
5
,
0
≤
k
<
n
1≤n≤5×10^5,0≤k<n
1≤n≤5×105,0≤k<n。
思路:
对于每一个数,可以分数位计算它对答案的贡献。
对于在
a
1
,
a
2
,
.
.
.
,
a
n
a_1,a_2,...,a_n
a1,a2,...,an中填入
m
m
m个加号:
a
1
a_1
a1作为个位的贡献为
1
×
a
1
×
C
n
−
2
m
−
1
1\times a_1\times C^{m-1}_{n-2}
1×a1×Cn−2m−1。(确定
a
1
a_1
a1后填加号,剩下排列组合)
作为十位为
10
×
a
1
×
C
n
−
3
m
−
2
10\times a_1\times C^{m-2}_{n-3}
10×a1×Cn−3m−2。
作为百位为
100
×
a
1
×
C
n
−
4
m
−
3
100\times a_1\times C^{m-3}_{n-4}
100×a1×Cn−4m−3。
.
.
.
a
2
a_2
a2作为个位的贡献为
1
×
a
2
×
C
n
−
2
m
−
1
1\times a_2\times C^{m-1}_{n-2}
1×a2×Cn−2m−1。
作为十位为
10
×
a
2
×
C
n
−
3
m
−
2
10\times a_2\times C^{m-2}_{n-3}
10×a2×Cn−3m−2。
.
.
.
a
3
a_3
a3作为个位的贡献为
1
×
a
3
×
C
n
−
2
m
−
1
1\times a_3\times C^{m-1}_{n-2}
1×a3×Cn−2m−1。
.
.
.
总结:答案为
∑
1
≤
i
≤
n
∑
0
≤
j
≤
m
i
n
(
n
−
3
,
m
−
1
)
1
0
j
×
a
i
×
C
n
−
j
−
2
m
−
j
−
1
\sum_{1\le i\le n}\sum_{0\le j\le min(n-3,m-1)}10^j\times a_i\times C^{m-j-1}_{n-j-2}
∑1≤i≤n∑0≤j≤min(n−3,m−1)10j×ai×Cn−j−2m−j−1
然而
O
(
n
2
)
O(n^2)
O(n2)肯定炸了……
发现一个系数和组合数对应多个
a
a
a值。
对
a
a
a前缀和处理,系数和组合数
O
(
n
)
O(n)
O(n)枚举,累加答案。
注意边界条件!
注意当
a
i
a_i
ai直到最后都不填加号的情况,组合数为
C
i
−
1
m
C^{m}_{i-1}
Ci−1m,与前面分开,
O
(
n
)
O(n)
O(n)处理!
代码:
#include<bits/stdc++.h>
using namespace std;
#define in Read()
#define LL long long
inline LL in{
LL s=0,f=1;char x;
for(x=getchar();!isdigit(x);x=getchar()) if(x=='-') f=-1;
for( ;isdigit(x);x=getchar()) s=(s<<1)+(s<<3)+(x&15);
return s*f;
}
const LL A=5e5+5;
const LL mod=998244353;
LL n,m;
char a[A];
LL p[A];
LL mul[A],inv[A],ans[A];
LL sum[A],be;
LL res;
inline void prepare(){
mul[1]=1;
for(int i=2;i<=n;i++)
mul[i]=mul[i-1]*i%mod;
inv[0]=inv[1]=1;
for(int i=2;i<=n;i++)
inv[i]=((-1)*((mod/i)*inv[mod%i])%mod+mod)%mod;
ans[0]=ans[1]=1;
for(int i=2;i<=n;i++)
ans[i]=((ans[i-1]*inv[i])%mod+mod)%mod;
return;
}
signed main(){
n=in,m=in;
prepare();
scanf("%s",a);
for(int i=1;i<=n;i++)
p[i]=a[i-1]-'0';
for(int i=1;i<=n;i++)
sum[i]=sum[i-1]+p[i];
be=1;
for(int i=2;i>0&&n-i>=m-1;i++){
LL c=((mul[n-i]*ans[m-1])%mod*ans[n-i-m+1])%mod;
res=(res+((c*be)%mod*sum[n-i+1])%mod)%mod;
be=be*10%mod;
}
be=1;
for(int i=n;i>=m+1;i--){
LL c=(((mul[i-1]*ans[m])%mod)*ans[i-m-1])%mod;
res=(res+((c*be)%mod*p[i])%mod);
be=be*10%mod;
}
printf("%lld",(res+mod)%mod);
return 0;
}