洛谷P6754题解
本文同步更新于洛谷博客
题目描述
给定 ,求区间 中有多少个不含长度大于一的回文子串的数字串。
题解
还是比较套路的数位 dp。我们传五个参数 进入 dfs,分别表示枚举到第 位,前两位为 ,前一位为 ,是否为前导 ,以及这一位填的数有没有限制,用 数组记忆化即可。
下面来简要说明一下如何判断非回文串。不妨设回文串为 ,接下来进行分类讨论:若 为奇数,令 ,则 必为回文串;若 为偶数,令 ,则 必为回文串。因此我们在填到第 位时,只需要判断它与第 位和第 位是否相等即可。
注意
我们把填前导 的位置设为 ,这样会更加方便,但是 和 为 的时候不能进行记忆化。
Code
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int len,a[20];
ll l,r,f[20][10][10];
ll dfs(int k,int x,int y,int p,int q)
{
if(!k)
return 1;
if(!p&&!q&&x!=-1&&y!=-1&&f[k][x][y]!=-1)
return f[k][x][y];
int z=q?a[k]:9;
ll res=0;
for(int i=0;i<=z;i++)
{
if(i==x||i==y)
continue;
res+=dfs(k-1,y,(p&&!i)?-1:i,p&&!i,q&&(i==z));
}
if(!p&&!q&&x!=-1&&y!=-1)
f[k][x][y]=res;
return res;
}
ll divide(ll x)
{
len=0;
while(x)
{
a[++len]=x%10;
x/=10;
}
return dfs(len,-1,-1,1,1);
}
int main()
{
memset(f,-1,sizeof(f));
scanf("%lld%lld",&l,&r);
printf("%lld\n",divide(r)-divide(l-1));
return 0;
}
本文作者:Ginger_he
本文链接:https://www.cnblogs.com/Gingerhe/p/15837884.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步