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;
} 
posted @ 2024-07-02 09:50  storms11  阅读(7)  评论(0编辑  收藏  举报