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;
}