码迷,mamicode.com
首页 > 其他好文 > 详细

LightOJ - 1205:Palindromic Numbers (数位DP&回文串)

时间:2018-11-18 23:05:59      阅读:265      评论:0      收藏:0      [点我收藏+]

标签:i++   open   play   pac   case   out   continue   isp   mic   

A palindromic number or numeral palindrome is a ‘symmetrical‘ number like 16461 that remains the same when its digits are reversed. In this problem you will be given two integers i j, you have to find the number of palindromic numbers between i and j (inclusive).

Input

Input starts with an integer T (≤ 200), denoting the number of test cases.

Each case starts with a line containing two integers i j (0 ≤ i, j ≤ 1017).

Output

For each case, print the case number and the total number of palindromic numbers between i and j (inclusive).

Sample Input

4

1 10

100 1

1 1000

1 10000

Sample Output

Case 1: 9

Case 2: 18

Case 3: 108

Case 4: 198

 

题意:求区间的回文串数量。

思路:从两头向中间靠,前缀是否小于原数用tag表示,后缀是否小于原数用ok表示,注意后缀尽管后面的比原位大,但是前面的小一点可以抵消其效果。

#include<bits/stdc++.h>
#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
ll dp[20][20][2][2]; int d[20],cnt;
ll get(int bg,int l,int r,int tag,bool ok)
{
    if(r>l) return !tag||(tag&&ok);
    if(!tag&&dp[bg][l][tag][ok]) return dp[bg][l][tag][ok];
    int lim=tag?d[l]:9; ll res=0;
    rep(i,0,lim){
        if(bg==l&&i==0) continue;
        bool g=ok;
        if(ok) g=i<=d[r];
        else g=i<d[r];
        res+=get(bg,l-1,r+1,tag&&(i==lim),g);
    }
    return tag?res:dp[bg][l][tag][ok]=res;
}
ll cal(ll x)
{
    if(x<0) return 0LL;if(x==0) return 1LL;
    ll res=1; cnt=0;
    while(x) d[++cnt]=x%10,x/=10;
    rep(i,1,cnt) res+=get(i,i,1,i==cnt,true);
    return res;
}
int main()
{
    int T,C=0; ll L,R; scanf("%d",&T);
    while(T--){
        scanf("%lld%lld",&L,&R); if(L>R) swap(L,R);
        printf("Case %d: %lld\n",++C,cal(R)-cal(L-1));
    }
    return 0;
}

有部分数组没有必要:

技术分享图片
#include<bits/stdc++.h>
#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
ll dp[20][20]; int d[20],cnt;
//tag维护前缀是否小于,ok维护后缀是否小于。维护二者不一样。
ll get(int bg,int l,int r,int tag,bool ok)
{
    if(r>l) return !tag||(tag&&ok);
    if(!tag&&dp[bg][l]) return dp[bg][l];
    int lim=tag?d[l]:9; ll res=0;
    rep(i,0,lim){
        if(bg==l&&i==0) continue;
        bool g=ok;
        if(ok) g=i<=d[r];
        else g=i<d[r];
        res+=get(bg,l-1,r+1,tag&&(i==lim),g);
    }
    return tag?res:dp[bg][l]=res;
}
ll cal(ll x)
{
    if(x<0) return 0LL;if(x==0) return 1LL;
    ll res=1; cnt=0;
    while(x) d[++cnt]=x%10,x/=10;
    rep(i,1,cnt) res+=get(i,i,1,i==cnt,true);
    return res;
}
int main()
{
    int T,C=0;ll L,R; scanf("%d",&T);
    while(T--){
        scanf("%lld%lld",&L,&R); if(L>R) swap(L,R);
        printf("Case %d: %lld\n",++C,cal(R)-cal(L-1));
    }
    return 0;
}
View Code

 

LightOJ - 1205:Palindromic Numbers (数位DP&回文串)

标签:i++   open   play   pac   case   out   continue   isp   mic   

原文地址:https://www.cnblogs.com/hua-dong/p/9980178.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!