20191112 csp-s模拟T3(组合计数)

T3 字符串问题(string)

(WOJ4818)
3.1 题目描述
经过一番斗争以后,高钧终于放弃了抵抗。现在高匀有一个长度为 n n n的由数字字符 0 ∼ 9 0∼9 09组成的字符串,在感受 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 09组成
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 1n5×105,0k<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×Cn2m1。(确定 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×Cn3m2
作为百位为 100 × a 1 × C n − 4 m − 3 100\times a_1\times C^{m-3}_{n-4} 100×a1×Cn4m3
.
.
.

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×Cn2m1
作为十位为 10 × a 2 × C n − 3 m − 2 10\times a_2\times C^{m-2}_{n-3} 10×a2×Cn3m2
.
.
.

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×Cn2m1
.
.
.

总结:答案为 ∑ 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} 1in0jmin(n3,m1)10j×ai×Cnj2mj1
然而 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} Ci1m,与前面分开, 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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值