1 条题解
-
0
自动搬运
来自洛谷,原作者为

George1123
**搬运于
2025-08-24 21:48:45,当前版本为作者最后更新于2020-02-25 17:46:27,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
题解-萌数
夫蒟蒻初学数位 ,寻水题而得《萌数》,乃谔谔做之。初适,做之悠然。而样例不过,渐生焦躁,AC时已过三,而错之甚奇,乃记之。
萌数 求区间 中有长度大于 的回文子串的数量。 数据范围:。
数位 典型题,如果你没学过数位 就跳进传送门→[传送门]。用记忆化搜索模型,用 表示 区间中的答案, 表示 的位数, 表示 从右往左第 位。
$$\texttt{Dfs(int~w,int~d,int~ld,bool~free,bool~hw)} $$表示:
当前要求从右往左第 位数。
第 位数为 。
第 位数为 。
如果前 位和 相同,;否则 。
如果前 位中已经出现了“长度大于 的回文子串”,;否则 。
的值表示数的数量。
如果找到的第 个数字 满足 或 ,就说明有了长度至少为 的回文子串。用 数字记下答案,完成记忆化搜索。
code
lng Dfs(int w,int d,int ld,bool free,bool hw){ if(!w) return hw; if(free&&~f[w][d][ld][hw]) return f[w][d][ld][hw]; int up=free?9:nl[w]; lng res=0; for(int i=0;i<=up;i++) (res+=Dfs(w-1,i,d,free||i<up,hw||i==d||i==ld))%=mod; /* 下一位是w-1位,下一个数的上一个数是i,下一个数的上上个数是d。 如果原来就free==1或者i与n的第w位不相同下一个free=1。 如果原来就有了长度为2的回文子串或i,d形成回文子串或i,d,ld形成回文子串,下一个fw=1。 */ if(free) f[w][d][ld][hw]=res; return res; }所以
$$\texttt{DP(n)}=\sum\limits_{i=1}^{p-1}\sum_{j=1}^{9}\texttt{Dfs(i-1,j,10,1,0)} +\sum_{j=1}^{nl_p-1}\texttt{Dfs(p-1,j,10,1,0)} +\texttt{Dfs(p-1,}nl_p\texttt{,10,0,0)}$$。为什么 ?因为 还不存在,而且如果你赋值为 ,会影响 结果;如果你赋值为 ,会在记忆化数组的下标上 。所以赋值为 是较好选择,然后记忆化数组的下标范围就要开 。蒟蒻因为这里赋值成 而 了两次。
code
lng DP(char*n,lng a){ int p=strlen(n+1); lng res=0; for(int i=1;i<=p;i++) nl[i]=n[p+1-i]-'0'; nl[1]+=a; if(p==1&&nl[1]<=0) return 0; for(int i=1;nl[i]<0&&i<=p;i++) nl[i]+=10,nl[i+1]--; while(!nl[p]&&p>1) p--; // debug(p,nl); memset(f,-1,sizeof f); for(int i=1;i<=p-1;i++) for(int j=1;j<=9;j++) (res+=Dfs(i-1,j,10,1,0))%=mod; for(int j=1;j<=nl[p];j++) (res+=Dfs(p-1,j,10,j<nl[p],0))%=mod; return res; }然后最后答案就是 ,因为 和 远爆 ,所以用字符串输入或处理。
#include <bits/stdc++.h> using namespace std; //&Start #define lng long long //&Debug template<class T> void debug(int x,T*arr){ for(int i=1;i<=x;i++) cout<<arr[i]<<"\n "[i<x]; } //&DP const int W=1010,D=10; const lng mod=1e9+7; char L[W],R[W]; int nl[W]; lng f[W][D][D+1][2]; lng Dfs(int w,int d,int ld,bool free,bool hw){ if(!w) return hw; if(free&&~f[w][d][ld][hw]) return f[w][d][ld][hw]; int up=free?9:nl[w]; lng res=0; for(int i=0;i<=up;i++) (res+=Dfs(w-1,i,d,free||i<up,hw||i==d||i==ld))%=mod; if(free) f[w][d][ld][hw]=res; return res; } lng DP(char*n,lng a){ int p=strlen(n+1); lng res=0; for(int i=1;i<=p;i++) nl[i]=n[p+1-i]-'0'; nl[1]+=a; if(p==1&&nl[1]<=0) return 0; for(int i=1;nl[i]<0&&i<=p;i++) nl[i]+=10,nl[i+1]--; while(!nl[p]&&p>1) p--; // debug(p,nl); memset(f,-1,sizeof f); for(int i=1;i<=p-1;i++) for(int j=1;j<=9;j++) (res+=Dfs(i-1,j,10,1,0))%=mod; for(int j=1;j<=nl[p];j++) (res+=Dfs(p-1,j,10,j<nl[p],0))%=mod; return res; } //&Main int main(){ scanf("%s %s",L+1,R+1); printf("%lld\n",(DP(R,0)-DP(L,-1)+mod)%mod); return 0; }祝大家学习愉快!
- 1
信息
- ID
- 2467
- 时间
- 1000ms
- 内存
- 512MiB
- 难度
- 6
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者