数位dp HDU - 5898 odd-even number

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

题意:求两个数中间的满足连续位是奇数的长度是偶数,连续位上是偶数的长度位奇数的数量。

分析:就是数位dp基本写法,dfs 的参数多加了个 a 表示连续位数的长度,flag表示上一位是否为奇数。  这里当奇偶改变时,a 就要变成1 ,并且可以用 a=0 来表示区分是前导0 。然后 记忆化搜索的过程中 ,用continue 表示不满足条件,暂时满足才往下接着搜索。

然后!!     &运算的优先程度比 ==运算小啊!  位运算还是多加括号吧

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

typedef long long ll;
const ll maxn =  9e18;
int n;

int dig[20];
ll dp[20][20][2][2];
int Max;

ll dfs(int pos,int a,int up,int flag){   //flag:上一位是否为奇数
    // printf("yes\n");
    if(pos<0){
        return 1;
    }
    if (!up && dp[pos][a][up][flag] != -1) return dp[pos][a][up][flag];
    ll res=0;
    for (int i = 0; i <= 9; i++) {

        // if(pos == Max && i==0) continue;

        if (up && (i > dig[pos])) break;
        int b;
        
        if(a==0&&i!=0){
            b=1;
        }
        else if(a==0&&i==0){
            b=0;
        }
        else if( pos == Max) b=1;
        else{ b= ((i&1)==flag)?a+1:1; }

        if(a!=0&&b==1){
            if(( flag&1 ) == (a&1)  ) { continue; }
        }
        // if(b==0) b++;
        if(pos==0 && ((i&1) == (b&1))) {  continue; }
        
        // printf("pos=%d i=%d \n", pos,i);
        // if(pos==0&&!(i&1) == (b&1)) printf("yes\n");
        res += dfs( pos-1, b,up && i == dig[pos],i&1 );
        // printf("res=%d\n", res);
    }
    if(!up) dp[pos][a][up][flag]=res;
    return res;
}

ll sol(ll x){
    if(x==0) return 0;
    if(x<0) return 0;
    int i=0;
    while(x){
        dig[i++] = x%10;
        x/=10; 
    }
    Max=i-1;
    return dfs(Max, 0, 1,  0 );
}

int main(){
    int T;
    scanf("%d",&T);
    ll x,y;
    int kase=1;
    memset(dp,-1,sizeof(dp));
    while(T--){
        scanf("%lld%lld",&x,&y);
        printf("Case #%d: %lld\n", kase++,sol(y)-sol(x-1));
    }

}

 

转载于:https://www.cnblogs.com/-Zzz-/p/11416645.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值