HDU 5898 (数位DP)

Posted Psong

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 5898 (数位DP)相关的知识,希望对你有一定的参考价值。

HDU 5898 odd-even number

题意:如果一个数连续的奇数之和为偶数,连续的偶数之和为奇数则满足条件,问某一区间内满足条件的数字的个数。

思路:数位DP,dp[i][j][k][u]表示计算到底i位,是否为临界值,上一位是奇还是偶,连续奇或偶有u个,在dfs是多记录一下该数前面是不是全为0以及该数是不是已近不满足条件。

技术分享
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long LL;
vector<int> v;
LL l,r;
LL dp[25][2][2][25];//第i位,是否为临界值,上一位是奇还是偶,连续或偶的个数
LL dfs(int pos,int pan,int status,int num,int ok1,int ok2){
    if(ok1) return 0;
    if(pos<0){
        if(ok2==0) return 0;
        if(status==1&&num%2==0)
            return 1;
        if(status==0&&num%2==1)
            return 1;
        return 0;
    }
    if(dp[pos][pan][status][num]!=-1)
        return dp[pos][pan][status][num];
    LL cnt=0;
    int k=pan?v[pos]:9;
    for(int i=0;i<=k;i++){
        int nowpan,nowstatus,nownum;
        int nowok1=0,nowok2=0;
        nowpan=(pan&&(i==k))?1:0;
        if(i==0){//该位为0
            if(ok2==0){//前面全是0
                nowok2=0;
                nownum=0;
                nowstatus=0;
            }
            else{//前面并非全是0
                nowok2=1;
                nowstatus=0;
                if(status==1){//前一个是奇,这个发生改变
                    nownum=1;
                    if(num%2==1)
                        nowok1=1;
                }
                else{//前一个是偶,这个继续
                    nownum=num+1;
                }
            }
        }
        else if(i%2==1){//非0且为奇
            nowok2=1;
            nowstatus=1;
            if(status==1){//前面为奇,继续
                nownum=num+1;
            }
            else{//前面为偶,发生改变
                nownum=1;
                if(num%2==0&&num!=0)
                    nowok1=1;
            }
        }
        else{//非0且为偶
            nowok2=1;
            nowstatus=0;
            if(status==1){//前面为奇,发生改变
                nownum=1;
                if(num%2==1&&num!=0)
                    nowok1=1;
            }
            else{//前面为偶,继续
                nownum=num+1;
            }
        }
        //printf("%d %d %d %d %d\n",nowpan,nowstatus,nownum,nowok1,nowok2);
        cnt+=dfs(pos-1,nowpan,nowstatus,nownum,nowok1,nowok2);
    }
    return dp[pos][pan][status][num]=cnt;
}
int main(){
    int t; cin>>t;
    int T=t;
    while(t--){
        cin>>l>>r;

        l--;
        v.clear();
        memset(dp,-1,sizeof(dp));
        while(l){
            v.push_back(l%10);
            l/=10;
        }
        int len=v.size()-1;
        LL a=dfs(len,1,1,0,0,0);

        v.clear();
        memset(dp,-1,sizeof(dp));
        while(r){
            v.push_back(r%10);
            r/=10;
        }
        len=v.size()-1;
        LL b=dfs(len,1,1,0,0,0);
        printf("Case #%d: ",T-t);
        cout<<b-a<<endl;
    }

    return 0;
}
Psong

 

以上是关于HDU 5898 (数位DP)的主要内容,如果未能解决你的问题,请参考以下文章

数位dp HDU - 5898 odd-even number

hdu 5898 odd-even number(数位dp)

hdu 5898 odd-even number 数位dp

hdu5898 odd-even number(数位dp)

hdu 5898 odd-even number 数位DP

[暑假集训--数位dp]hdu5898 odd-even number