P6754 [BalticOI 2013 Day1] Palindrome-Free Numbers
数据范围一眼数位dp。
关键条件为如果一个数字串的一个长度大于 11 的子串也为回文串的话,那么我们也定义这个数字串为回文串。
仔细思考发现一旦两个连续的数相同(偶回文)或两个数隔一个数相同(奇回文)都是回文,所以要保证连续三个数不相同,记录前两位即可。
注意事项:
1.前导零不应为0,防止前导零影响结果,可设为-1。
2.因为前两位可能有前导零,记忆化搜索可能越界,应搜索和记录时数值+1。
3.0<=l,所以有可能将出现求负数,应特判。(提示我们数位dp的一种可能错误)
#include <bits/stdc++.h>
using namespace std;
#define ll long long
ll a,b,dp[20][20][20];
int sh[20];
ll dfs(int cur,bool qdl,bool lim,int x2,int x1)
{
if(cur==0)return 1;
if(!qdl&&!lim&&~dp[cur][x2+1][x1+1])return dp[cur][x2+1][x1+1];
int z=lim?sh[cur]:9;
ll sum=0;
for(int i=0;i<=z;i++)
{
if(x2==i||x1==i)continue;
sum+=dfs(cur-1,qdl&(i==0),lim&(i==z),x1,(!qdl||i)?i:-1);
}
if(!qdl&&!lim)dp[cur][x2+1][x1+1]=sum;
return sum;
}
ll find(ll x)
{
if(x<0)return 0;
ll ans=0;int pos=0;
while(x>0)
{
sh[++pos]=x%10;
x/=10;
}
ans=dfs(pos,1,1,-1,-1);
return ans;
}
int main()
{
memset(dp,-1,sizeof(dp));
scanf("%lld%lld",&a,&b);
printf("%lld\n",find(b)-find(a-1));
return 0;
}

浙公网安备 33010602011771号