ABC 045/C 思考及拓展
链接:https://atcoder.jp/contests/abc045/tasks/arc061_a
给出一列长度不大于10的数字列,使用‘+’进行分割,求所有方案得到的所有数字之和。
主要有三个点:
(1)由于数值比较小,所以可以使用二进制枚举,由于之前没有用过 bitset,主要是使用bitset要注意一下 \(bitset<size\_t\ N>\),bitset定义时需要固定的值N,可以使用[]进行取值也可以直接被输出,并且从小到大与二进制表示是一样的,比如 6=011000000,不管N是多长都可以从0开始取值,在重定义时 \(a=bitset<n>(x)\),要把n,x写好。
(2)优先考虑DP,可以考虑三维 \(dp[l][k][s]\),表示前l个数字,最后一个数字由k开始,目前的和为s。 考虑到s数值范围已经爆炸了,数组要记录的状态信息过多,空间支撑不了。
(3)考虑如果扩大字符串的长度,由之前的\(length\le 10\) 到 \(length\le 1e5/1e6?\) :
观察到,每个子串\(s[i..j]\)的数值可以表示为\(s[i] * 10^{j-i} + s[i+1] * 10^{j-i-1} + ... + s[j] * 10^0\), 因此,将总和分解为每个字符 $ s[k] $ 的贡献,通过数学公式计算每个字符在所有可能分割方式中的总贡献,最终累加所有字符的贡献。每个字符 $ s[k] $ 的贡献取决于其在子串 $ s[i..j] $ 中的位置。
具体来说,字符 $ s[k] $ 在子串中的权重为 $ 10^{j-k} $,且子串的出现次数由左右分割方式的数目决定:若子串起始位置为 $ i $,则左边的分割方式数目为 $ 2^{i-1} $;若子串结束位置为 $ j $,则右边的分割方式数目为 $ 2^{n-j-2} $,字符 $ s[k] $ 的总贡献为:
其中:
整理可得:
这样每个数字字符遍历一遍加和,即可O(n)得到最终结果。

浙公网安备 33010602011771号