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; }