首页 > 代码库 > [LightOJ1205]Palindromic Numbers(数位dp)

[LightOJ1205]Palindromic Numbers(数位dp)

题目链接:http://lightoj.com/volume_showproblem.php?problem=1205

题意:求[l,r]内回文数的数量。

dp(s,l,ok)表示数字以s为开头,长度为l的时是/不是回文数

dp(s,l,ok)可以由dp(s,l-1,ok)更新来,当且仅当接下来插入的一位与s对应的位置相同。

 1 #include <bits/stdc++.h> 2 using namespace std; 3  4 typedef long long LL; 5 const int maxn = 22; 6 int digit[maxn], rev[maxn]; 7 LL dp[maxn][maxn][2]; 8 LL l, r; 9 10 LL dfs(int s, int l, bool ok, bool flag) {11   if(l < 0) return ok;12   if(!flag && ~dp[s][l][ok]) return dp[s][l][ok];13   int pos = flag ? digit[l] : 9;14   LL ret = 0;15   for(int i = 0; i <= pos; i++) {16     rev[l] = i;17     if(i == 0 && s == l) ret += dfs(s-1, l-1, ok, flag&&(i==pos));18     else if(ok && l < (s + 1) / 2) ret += dfs(s, l-1, i==rev[s-l], flag&&(i==pos));19     else ret += dfs(s, l-1, ok, flag&&(i==pos));20   }21   if(!flag) dp[s][l][ok] = ret;22   return ret;23 }24 25 LL f(LL x) {26   int pos = 0;27   while(x) {28     digit[pos++] = x % 10;29     x /= 10;30   }31   return dfs(pos-1, pos-1, true, true);32 }33 34 int main() {35   //freopen("in", "r", stdin);36   int T, _ = 1;37   scanf("%d", &T);38   memset(dp, -1, sizeof(dp));39   while(T--) {40     scanf("%lld%lld",&l,&r);41     if(l > r) swap(l, r);42     printf("Case %d: %lld\n", _++, f(r) - f(l-1));43   }44   return 0;45 }

 

[LightOJ1205]Palindromic Numbers(数位dp)