HDU 5898 odd-even number 数位DP

odd-even number

题目连接:

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

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

Hint

题意:

一个数字,它每个数位上的奇数都形成偶数长度的段,偶数位都形成奇数长度的段他就是好的。问[L , R]的好数个数。

题解

直接数位DP就好了。。。。

因为数据范围很小,所以怎么写都可以

代码

#include <bits/stdc++.h>

using namespace std;

const int maxn = 20 + 15;

long long dp[maxn][2][2][2][2];

char str[maxn] ;

inline void up( long long & x , long long v ){ x += v;}

long long solve( long long x ){
    if( x == 0 ) return 1;
    memset( dp  , 0 , sizeof( dp ) );
    int len = 0 ;
    while( x > 0 ){
        str[ ++ len ] = x % 10 + '0';
        x /= 10;
    }
    str[len + 1] = 0;
    reverse( str + 1 , str + len + 1 );
    //cout << "check num is " << str + 1 << endl;
    dp[0][1][0][0][1] = 1;
    for(int i = 0 ; i < len ; ++ i)
        for(int lead = 0 ; lead < 2 ; ++ lead)
            for(int f = 0 ; f < 2 ; ++ f)
                for(int pre = 0 ; pre < 2 ; ++ pre)
                    for(int cur = 0 ; cur < 2 ; ++ cur)
                        if( dp[i][lead][f][pre][cur] ){
                            int ed = f ? 9 : str[i + 1] - '0';
                            for(int add = 0 ; add <= ed ; ++ add){
                                int newf = f | (add < ed);
                                if( lead == 1 ){
                                    if( add == 0 ) up( dp[i + 1][lead][newf][pre][cur] , dp[i][lead][f][pre][cur] );
                                    else up( dp[i + 1][0][newf][add & 1][1] , dp[i][lead][f][pre][cur] );
                                }else{
                                    if( ( add & 1 ) == pre ) up( dp[i + 1][lead][newf][add & 1][cur ^ 1] , dp[i][lead][f][pre][cur] );
                                    else{
                                        if( pre == cur ) continue;
                                        up( dp[i + 1][lead][newf][add & 1][1] , dp[i][lead][f][pre][cur] );
                                    }
                                }
                            }
                        }
    long long ans = 0;
    for(int lead = 0 ; lead < 2 ; ++ lead ) for(int f = 0 ; f < 2 ; ++ f) for(int pre = 0 ; pre < 2 ; ++ pre) up( ans , dp[len][lead][f][pre][pre ^ 1] );
    return ans;
}

int main( int argc , char * argv[] ){
    int T , cas = 0;
    scanf( "%d" , & T );
    while( T -- ){
        long long L , R ;
        scanf( "%I64d%I64d" , & L , & R );
        printf( "Case #%d: %I64d\n" , ++ cas , solve( R ) - solve( L - 1 ) );
    }
    return 0;
}
posted @ 2016-09-20 23:24  qscqesze  阅读(421)  评论(0编辑  收藏  举报