HDU 5898 基础数位DP

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

 

题意:统计  连续的奇数必须是偶数个,连续的偶数必须是奇数个。。的个数

 

思路:dp[ i ] [ j ] [ k ]  前i位 上一位是j  连续的奇数或者偶数有k。。

 

blog里面数位dp比较少,贴一个上来。。。

 

代码:

 

#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <iostream>
#include <cstring>
using namespace std;

typedef long long ll;
int a[20];
ll dp[20][11][20];//不同题目状态不同
ll dfs(int pos,int state,int ok,bool lead/*前导零*/,bool limit/*数位上界变量*/)
{
    if(pos==-1&&(state+ok)%2==1) return 1;
    if(pos==-1&&(state+ok)%2==0) return 0;

    if(!limit && !lead && dp[pos][state][ok]!=-1) return dp[pos][state][ok];

    int up=limit?a[pos]:9;
    ll ans=0;
    if(lead){
        for(int i=0;i<=up;i++){
            ans+=dfs(pos-1,i,1,lead && i==0,limit && i==a[pos]);
        }
    }
    else if((state+ok)%2==1){
        for(int i=0;i<=up;i++){
            if((i+state)%2==0)
                ans+=dfs(pos-1,i,ok+1,lead && i==0,limit && i==a[pos]);
            else
                ans+=dfs(pos-1,i,1,lead && i==0,limit && i==a[pos]);
        }
    }
    else{
        for(int i=0;i<=up;i++){
            if((i+state)%2==0)
                ans+=dfs(pos-1,i,ok+1,lead && i==0,limit && i==a[pos]);
        }
    }
    if(!limit && !lead) dp[pos][state][ok]=ans;
    return ans;
}
ll solve(ll x)
{
    int pos=0;
    a[0]=0;
    while(x)
    {
        a[pos++]=x%10;//编号为[0,pos),
        x/=10;
    }
    return dfs(pos-1/*从最高位开始枚举*/,10,1,true,true);
}
int main()
{
    ll le,ri;
    int cas=1;
    int t;
    scanf("%d",&t);
    memset(dp,-1,sizeof(dp));
    while(t--){
        scanf("%lld%lld",&le,&ri);
        printf("Case #%d: %lld\n",cas++,solve(ri)-solve(le-1));
    }
}



posted @ 2016-09-21 16:43  zhangxianlong  阅读(90)  评论(0编辑  收藏  举报