不是讨论区题解。
此题你需要向 AC 自动机里添加若干大于等于 L 且小于等于 R 的前缀。你当然可以像第一篇题解一样对上下边界都进行分讨,但这还要分位数讨论,感觉细节不少。
回想起不少数位 dp 的题目,当他询问 L 至 R 的答案时,我们通常会求 f(R)−f(L−1)。此题虽然问的并不满足可减性,但一个数的贡献是可减的。于是,我们可以先将 1 至 R 添入,然后再将 1 至 L-1 删除。添入时将对应终止节点的 g 加一,删除时将对应终止节点的 g 减一。
这个做法有个细节需要注意:因为你有了删除,有部分节点的 f 和 g 会是负的,这个时候如果你 f 初值设为 0,将会导致你在其中一步可能无法转移,这不仅会让你无法输出正确方案,甚至有可能让你算出更大的 f。因此你的 f 应当设为 -inf(不过似乎设成 -inf 好像一直都没问题,不如以后都直接设了算了?)
下面给个添加的实现方式,删除的话在 AC 自动机里改一下对 g 的修改就行了。
void add(string s){
int len=s.length();
for(ri i=1;i<len;i++){
for(ri j=1;j<10;j++)ACAM::add(char(j+'0')+(string)(""),i-1);
}
ACAM::add(s,0);
string now="";
for(ri i=0;i<len;i++){
for(ri j=(i?0:1);j+'0'<s[i];j++)ACAM::add(now+char(j+'0'),len-i-1);
now+=s[i];
}
}