【hdu5898】【数位DP】odd-even number 【连续奇数长度为偶数,连续的偶数的长度是奇数】

本文详细解析了HDU5898题目中的奇偶数问题,通过动态规划的方法解决了求解两个给定数值范围内满足特定奇偶条件的数的数量问题。

传送门:HDU 5898 odd-even number

描述:

odd-even number

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


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
 

Source
 

Recommend
wange2014   |   We have carefully selected several similar problems for you:   5899  5897  5896  5894  5893 
题意:

连续奇数长度为偶数,连续的偶数的长度是奇数,求有多少种

思路:

dp[i][j][k]的定义是i位数,首位为j,k=1时表示满足条件,k=0的时候表示可能转化为满足条件的数,处理出来之后数位DP就可以了

主循环当中不计算前导0,而是另外使用一个循环来计算含有前导0的情况下满足条件的数的数量

代码:

#include<bits/stdc++.h>
#define ll __int64
using  namespace std;

ll dp[20][10][2];
ll l,r;
int kase=1;

void init(){
  memset(dp, 0, sizeof(dp));
  for(int i=0; i<10; i++){
    if((i&1)==0)dp[1][i][1]=1;
    else dp[1][i][0]=1;
  }
  for(int i=2; i<=20; i++){
    for(int j=0; j<10; j++){
      for(int k=0; k<10; k++){
        if((j&1)==(k&1)){
          dp[i][j][1]+=dp[i-1][k][0];
          dp[i][j][0]+=dp[i-1][k][1];
        }
        else if(j&1)dp[i][j][0]+=dp[i-1][k][1];
        else dp[i][j][1]+=dp[i-1][k][1];
      }
    }
  }
}

ll solve(ll cur){
  int a[105],bit=0;
  ll tmp=cur,ans=0;
  int num=0;
  while(tmp){
    a[++bit]=tmp%10;
    tmp/=10;
  }
  a[bit+1]=0;

  for(int i=bit; i>=1; i--){
    //printf("%d\n",num);
    for(int j=0; j<a[i]; j++){
      if(bit==i && j>0)ans+=dp[i][j][1];
      else if(i<bit){
        if(j&1){
          if(a[i+1]%2==0 && (num&1))
            ans+=dp[i][j][1];
          else if(a[i+1]%2==1 && (num&1))
            ans+=dp[i][j][0];
          else if(a[i+1]%2==1 && !(num&1))
            ans+=dp[i][j][1];
        }
        else{
          if((a[i+1]%2==1)&& num%2==0)
            ans+=dp[i][j][1];
          else if(a[i+1]%2==0 && num%2==0)
            ans+=dp[i][j][1];
          else if((a[i+1]%2==0)&&(num%2==1))
            ans+=dp[i][j][0];
        }
      }
    }
    if(i==bit){
      num=1;
      continue;
    }
    if((a[i]&1)!=(a[i+1]&1)){
      if((a[i+1]&1)&&(num&1))break;
      if(!(a[i+1]&1)&&!(num&1))break;
      num=1;
    }
    else num++;
  }
    //solve the leading zero case
    for(int i=bit-1; i>=1; i--){
        for(int j=1; j<=9; j++)
            ans+=dp[i][j][1];
    }
  return ans;
}

int  main(){
//  #ifndef ONLINE_JUDGE
//  freopen("in.txt","r",stdin);
//  #endif

  int t;
  scanf("%d",&t);
  init();
  while(t--){
    scanf("%I64d%I64d",&l,&r);
    printf("Case #%d: %I64d\n",kase++,solve(r+1)-solve(l));
  }
  return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值