• HDU 5898 odd-even number 数位dp


    题目链接:

    http://acm.hdu.edu.cn/showproblem.php?pid=5898

    odd-even number

    Time Limit: 2000/1000 MS (Java/Others)
    Memory Limit: 65536/65536 K (Java/Others)
    #### 问题描述 > For a number,if the length of continuous odd digits is even and the length of continuous even digits is odd,we call it odd-even number.Now we want to know the amount of odd-even number between L,R(1<=L<=R<= 9*10^18).

    输入

    First line a t,then t cases.every line contains two integers L and R.

    输出

    Print the output for each case on one line in the format as shown below.

    样例输入

    2
    1 100
    110 220

    样例输出

    Case #1: 29
    Case #2: 36

    题意

    求[l,r]区间里面满足任意连续个数位为偶数的长度为奇数,任意连续个数位为奇数的长度为偶数,比如110,1100033334等。

    题解

    数位dp具体看代码注释

    #include<map>
    #include<set>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<ctime>
    #include<vector>
    #include<cstdio>
    #include<string>
    #include<bitset>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<functional>
    using namespace std;
    #define X first
    #define Y second
    #define mkp make_pair
    #define lson (o<<1)
    #define rson ((o<<1)|1)
    #define mid (l+(r-l)/2)
    #define sz() size()
    #define pb(v) push_back(v)
    #define all(o) (o).begin(),(o).end()
    #define clr(a,v) memset(a,v,sizeof(a))
    #define bug(a) cout<<#a<<" = "<<a<<endl
    #define rep(i,a,b) for(int i=a;i<(b);i++)
    #define scf scanf
    #define prf printf
    
    typedef long long  LL;
    typedef vector<int> VI;
    typedef pair<int,int> PII;
    typedef vector<pair<int,int> > VPII;
    
    const int INF=0x3f3f3f3f;
    const LL INFL=0x3f3f3f3f3f3f3f3fLL;
    const double eps=1e-6;
    const double PI = acos(-1.0);
    
    //start----------------------------------------------------------------------
    
    const int maxn=22;
    
    int arr[maxn],tot;
    LL dp[maxn][2][2];
    ///dp[i][0][0]表示长度为i,最后偶数位为偶数的情况
    ///dp[i][0][1]表示长度为i,最后奇数位为偶数的情况
    ///dp[i][1][0]表示长度为i,最后偶数位为奇数的情况
    ///dp[i][1][1]表示长度为i,最后奇数位为奇数的情况
    LL dfs(int len,int x,int y,bool ismax,bool iszer) {
        if (len == 0) {
            ///递归边界
            return y^1;
        }
        if (!ismax&&!iszer&&dp[len][x][y]>=0) return dp[len][x][y];
        LL res = 0;
        int ed = ismax ? arr[len] : 9;
    
        ///这里写递推的代码
        if(x==0){
            for(int i=0;i<=ed;i+=2){
                if(i==0&&iszer){
                    ///处理前导零
                    res+=dfs(len-1,0,1,ismax&&i==ed,iszer&&i==0);
                    res+=dfs(len-1,1,0,ismax&&i==ed,iszer&&i==0);
                }
                else{
                    ///后面接的还是偶数的情况
                    res+=dfs(len-1,0,y^1,ismax&&i==ed,iszer&&i==0);
                    ///后面能接奇数的情况
                    if(y==1&&len>1) res+=dfs(len-1,1,0,ismax&&i==ed,iszer&&i==0);
                }
            }
        }else{
            for(int i=1;i<=ed;i+=2){
                ///后面接的还是奇数的情况
                res+=dfs(len-1,1,y^1,ismax&&i==ed,iszer&&i==0);
                ///后面接的是偶数的情况
                if(y==1&&len>1) res+=dfs(len-1,0,1,ismax&&i==ed,iszer&&i==0);
            }
        }
        ///这里记忆化存的必须保证没有前导零的情况!,有前导零的要单独计算
        return ismax||iszer ? res : dp[len][x][y] = res;
    }
    
    LL solve(LL x) {
        tot = 0;
        while (x) { arr[++tot] = x % 10; x /= 10; }
        LL even=dfs(tot, 0,1, true,true);
        LL odd=dfs(tot,1,0,true,true);
        return even+odd;
    }
    
    void init(){
        clr(dp,-1);
    }
    
    int main() {
        int tc,kase=0;
        scf("%d",&tc);
        init();
        while(tc--){
            LL x,y;
            scf("%lld%lld",&x,&y);
            prf("Case #%d: %lld
    ",++kase,solve(y)-solve(x-1));
        }
        return 0;
    }
    
    //end-----------------------------------------------------------------------
    

    再回顾一发:

    #include<map>
    #include<set>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<ctime>
    #include<vector>
    #include<cstdio>
    #include<string>
    #include<bitset>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<functional>
    using namespace std;
    #define X first
    #define Y second
    #define mkp make_pair
    #define lson (o<<1)
    #define rson ((o<<1)|1)
    #define mid (l+(r-l)/2)
    #define sz() size()
    #define pb(v) push_back(v)
    #define all(o) (o).begin(),(o).end()
    #define clr(a,v) memset(a,v,sizeof(a))
    #define bug(a) cout<<#a<<" = "<<a<<endl
    #define rep(i,a,b) for(int i=a;i<(b);i++)
    #define scf scanf
    #define prf printf
    
    typedef long long LL;
    typedef vector<int> VI;
    typedef pair<int,int> PII;
    typedef vector<pair<int,int> > VPII;
    
    const int INF=0x3f3f3f3f;
    const LL INFL=10000000000000000LL;
    const double eps=1e-9;
    
    const double PI = acos(-1.0);
    
    //start----------------------------------------------------------------------
    
    LL dp[22][3][2];
    int arr[22],tot;
    ///k==0表示上一位不存在,k==1表示上一位为奇数,k==2表示上一位为偶数
    ///l==0表示上一位连续偶数个奇数或偶数的情况
    LL dfs(int len,int k,int l, bool ismax,bool iszer) {
        if (len == 0) {
            if(l==0) return 1LL;
            return 0;
        }
        if (!ismax&&dp[len][k][l]>=0) return dp[len][k][l];
        LL res = 0;
        int ed = ismax ? arr[len] : 9;
    
        ///这里插入递推公式
        for (int i = 0; i <= ed; i++) {
            if(i==0&&iszer){
                ///处理前导零
                res+=dfs(len-1,0,0,ismax&&i==ed,iszer&&i==0);
            }else{
                if(k==0){
                    if(i&1) res+=dfs(len-1,1,1,ismax&&i==ed,iszer&&i==0);
                    else res+=dfs(len-1,2,0,ismax&&i==ed,iszer&&i==0);
                }else if(k==1){
                    if(i&1){
                        res+=dfs(len-1,k,l^1,ismax&&i==ed,iszer&&i==0);
                    }else{
                        if(l==0) res+=dfs(len-1,2,0,ismax&&i==ed,iszer&&i==0);
                    }
                }else if(k==2){
                    if(!(i&1)){
                        res+=dfs(len-1,k,l^1,ismax&&i==ed,iszer&&i==0);
                    }else{
                        if(l==0) res+=dfs(len-1,1,1,ismax&&i==ed,iszer&&i==0);
                    }
                }
            }
        }
        return ismax ? res : dp[len][k][l] = res;
    }
    
    LL solve(LL x) {
        tot = 0;
        while (x) { arr[++tot] = x % 10; x /= 10; }
        return dfs(tot,0,0,true,true);
    }
    
    int main() {
        clr(dp,-1);
        int tc,kase=0;
        scf("%d",&tc);
        while(tc--){
            LL l,r;
            scf("%lld%lld",&l,&r);
            prf("Case #%d: %lld
    ",++kase,solve(r)-solve(l-1));
        }
        return 0;
    }
    
    //end-----------------------------------------------------------------------
    

    精简版:

    #include<map>
    #include<set>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<ctime>
    #include<vector>
    #include<cstdio>
    #include<string>
    #include<bitset>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<functional>
    using namespace std;
    #define X first
    #define Y second
    #define mkp make_pair
    #define lson (o<<1)
    #define rson ((o<<1)|1)
    #define mid (l+(r-l)/2)
    #define sz() size()
    #define pb(v) push_back(v)
    #define all(o) (o).begin(),(o).end()
    #define clr(a,v) memset(a,v,sizeof(a))
    #define bug(a) cout<<#a<<" = "<<a<<endl
    #define rep(i,a,b) for(int i=a;i<(b);i++)
    #define scf scanf
    #define prf printf
    
    typedef long long LL;
    typedef vector<int> VI;
    typedef pair<int,int> PII;
    typedef vector<pair<int,int> > VPII;
    
    const int INF=0x3f3f3f3f;
    const LL INFL=10000000000000000LL;
    const double eps=1e-9;
    
    const double PI = acos(-1.0);
    
    //start----------------------------------------------------------------------
    
    LL dp[22][3][2];
    int arr[22],tot;
    ///k==0表示上一位不存在,k==1表示上一位为奇数,k==2表示上一位为偶数
    ///l==0表示上一位连续偶数个奇数或偶数的情况
    LL dfs(int len,int k,int l, bool ismax,bool iszer) {
        if (len == 0) return l^1;
        if (!ismax&&dp[len][k][l]>=0) return dp[len][k][l];
    
        LL res = 0;
        int ed = ismax ? arr[len] : 9;
        for (int i = 0; i <= ed; i++) {
            if(i==0&&iszer){
                res+=dfs(len-1,2,0,ismax&&i==ed,iszer&&i==0);
            }else{
                if(k==2){
                    if(i&1) res+=dfs(len-1,1,1,ismax&&i==ed,iszer&&i==0);
                    else res+=dfs(len-1,0,0,ismax&&i==ed,iszer&&i==0);
                }else{
                    if(!(k^(i&1))) res+=dfs(len-1,k,l^1,ismax&&i==ed,iszer&&i==0);
                    else if(!l) res+=dfs(len-1,!k,!k,ismax&&i==ed,iszer&&i==0);
                }
            }
        }
        return ismax ? res : dp[len][k][l] = res;
    }
    
    LL solve(LL x) {
        tot = 0;
        while (x) { arr[++tot] = x % 10; x /= 10; }
        return dfs(tot,2,0,true,true);
    }
    
    int main() {
        clr(dp,-1);
        int tc,kase=0;
        scf("%d",&tc);
        while(tc--){
            LL l,r;
            scf("%lld%lld",&l,&r);
            prf("Case #%d: %lld
    ",++kase,solve(r)-solve(l-1));
        }
        return 0;
    }
    
    //end-----------------------------------------------------------------------
    

    Notes

    数位dp,比赛的时候思路歪了,干了两个多小时没出样例。。第二天条整思路之后,又调了一个上午。。。。orz,dp弱渣。。。

  • 相关阅读:
    xunjian.sh
    192.168.50.235配置
    自动备份并删除旧日志
    bg和fg命令
    linux之sed用法
    正则表示第二行,第二列
    linux下redis安装
    Hma梳理
    linux 系统监控、诊断工具之 lsof 用法简介
    java的基本数据类型有八种
  • 原文地址:https://www.cnblogs.com/fenice/p/5884938.html
Copyright © 2020-2023  润新知