HDU 5898 数位DP

7 篇文章 0 订阅

题目

odd-even number

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1109    Accepted Submission(s): 594


Problem Description
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).
 

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

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

Sample Input
  
  
2 1 100 110 220
 

Sample Output
  
  
Case #1: 29 Case #2: 36

题目大意


  这里我一定要吐槽一下出题人的英语水平,真的两眼真诚的等着题干老半天,表示直接给绕晕了

  题目大体意思是这样来的,让我们找一个叫做奇偶数的东西,什么样的数叫做奇偶数呢,如果这个数里面有连续的奇数,那么连续的奇数的个数一定要是偶数个,比如3333,四个连续的奇数,并且是偶数个,如果这个数里面有连续的偶数,那么连续的偶数的个数一定要是奇数个,比如66666,这里举一个反例122223,里面连续的奇数1,3都是奇数个,连续的偶数2222是偶数个


解题思路

 看了半天把题目看懂了,然后发现自己好像看懂了也不会,网上看的题解,然后Get新技能,数位DP

 这里是参考的牛人的博客,跟他学的数位DP,看完了再来看我的代码,应该看起来很舒服 传送门 :http://blog.csdn.net/wust_zzwh/article/details/52100392


#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define LL long long
LL L,R;
int case_=1;
LL dp[26][26][26];
LL bit[26];
LL dfs(int pos, int pre ,int len ,int zero, int limit)
{
    if(pos<=0) return (pre&1)!=(len&1);
    if(!limit&&dp[pos][pre][len]!=-1) return dp[pos][pre][len];
    int up=limit?bit[pos]:9;
    LL ans=0;
    for(int i=0;i<=up;i++)
    {
        if(zero)
        {
            if(i==0)
                ans+=dfs(pos-1,0,0,1,limit&&i==bit[pos]);
            else
                ans+=dfs(pos-1,i&1,len+1,0,limit&&i==bit[pos]);
        }
        else if(i&1)///当前位是奇数
        {
            if(pre&1)///前一位也是奇数,那么继续向下深入
                ans+=dfs(pos-1,i&1,len+1,0,limit&&i==bit[pos]);
            else ///前一位是偶数
            {
                if((pre&1)!=(len&1))
                    ans+=dfs(pos-1,i&1,1,0,limit&&i==bit[pos]);
            }
        }
        else ///当前位是偶数
        {
            if(pre&1)
            {
                if((pre&1)!=(len&1))
                     ans+=dfs(pos-1,i&1,1,0,limit&&i==bit[pos]);
            }
            else
                ans+=dfs(pos-1,i&1,len+1,0,limit&&i==bit[pos]);
        }

    }
    if(!limit) dp[pos][pre][len]=ans;
    return ans;
}
LL solve(LL x)
{
    ///cout<<"come in\n";
    memset(dp,-1,sizeof(dp));
    int pos=0;
    while(x)
    {
        bit[++pos]=x%10;
        x/=10;
    }
    ///cout<<"solve\n";
    return dfs(pos,0,0,1,1);
    ///cout<<"dfs\n";
}
void work()
{
    scanf("%lld%lld",&L,&R);
    printf("Case #%d: %lld\n",case_++,solve(R)-solve(L-1));
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        work();
    }
    return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值