ABC338G 题解
计数题,没有太多思维难度,就是麻烦。
显然 +
和 *
是比较难搞的,应考虑子问题。
复杂度要求线性,考虑每个位置的贡献。
Case 1:只有数字
Ex: 1234
考虑 2
的贡献,枚举一下看看。
- \(12=1\times 10+2\times1\)
- \(123=1\times 100+2\times10+3\times1\)
- \(1234=\dots\)
- \(2=2\times1\)
- \(23=2\times 10+3\times 1\)
- \(234=\dots\)
2
贡献了 \(2\times 111=222\) 次。
引理:总贡献次数 \(=\) 左边 \(\times\) 右边
例如:12
中 2
贡献了 \(2\) 次,234
中 2
贡献了 \(111\) 次,1234
中正好是 \(2\times111\) 次。
设当前是第 \(p\) 位,长度为 \(n\),则总贡献次数为 \(p\times\sum\limits_{i=0}^{n-p} 10^i\)。
证明显然,请读者自行完成。
Case 2:只有数字 & +
Ex: 99+1234+999
仍然考虑 2
的贡献次数,请读者仿照 Case 1 自行枚举。
发现第一个加号前和第二个加号后的内容是不影响答案的,故可以只考虑两加号之间的部分,最后加上前后长度即可。
设当前位置、后面第一个加号位置为 \(s,t\),当前忽略加号的位置为 \(pd\),总数字量为 \(n\),则总贡献次数为
\(pd\times\left(\sum\limits_{i=0}^{t-s-1} 10^i+ (n-pd)\times10^{t-s-1}\right)\)。
好长的式子。
Case 3:数字 & +
& *
(原问题)
先解决算重复的问题。
比如 2*3
中,\(2\times3\) 只应该被计算一次,但如果计算贡献,会在 2
和 3
上分别统计一次,就算重了。
key:只在最后一个数上统计乘法答案(结合律)。
(当然你也可以在第一个数上计算,只不过从左到右扫,在最后统计更方便)
2*3
中,2
贡献 \(1\) 次,3
贡献 \(2+1=3\) 次。
Ex: 99+345*456*567*12+999
通过 Case 2 我们发现,可以把整个串用 +
号分割,每一小段单独考虑。
故统计 2
的答案,只需要看 345*456*567*12
这一部分,请读者自行枚举。
发现乘法对 2
的贡献就是345*456*567
的后缀贡献和,这是很容易 dp 计算的。具体说,就是每个数计算和,乘上后面的数,滚雪球。
\(\big[(3\times 100+4\times20+5\times3)\times 456+(4\times100+5\times20+6\times3)\big]\times 567 + \dots\)
加法的贡献和 Case 2 相同,不多赘述。
注意:乘法中非最后一个数的,向右只考虑乘号前、加号后的部分(反之亦然)!
例如 3
只考虑 345
和 999
,乘法部分不算。
小结
- 分成 \(3\) 个子问题考虑。
- 从简单开始枚举。
- 考虑每个位置的贡献。
- 分治(左右 & 符号分段)。
- 相同的部分合并计算。
- 乘法只算一次。
代码不难写,注意下标 & 取模的细节。
标签:Case,1234,题解,贡献,ABC338G,加号,考虑,times From: https://www.cnblogs.com/Cindy-Li/p/18048099