HDU 5898 odd-even number (数位DP)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sdz20172133/article/details/82431229

odd-even number

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

 

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.

扫描二维码关注公众号,回复: 3135429 查看本文章

 

 

Sample Input

2 1 100 110 220

 

 

Sample Output

Case #1: 29 Case #2: 36

 

 

Source

2016 ACM/ICPC Asia Regional Shenyang Online


 

算法分析:

题意:

[L,R]奇偶数的个数,奇偶数定义:如果一个数中连续的奇数有偶数个,连续的偶数有奇数个,那么这个数就是奇偶数

分析:

简单数位dp,我们用dp[pos][pre][state],表示第pos位为pre,如果pre为奇数,那么state表示和pre连续的奇数有state个,如果pre为偶数就表示和pre连续的偶数有state个,显然0<=pre<=9,state<19;

注意要记录前导零,因为前导零会影响连续偶数的长度

0个奇数也满足偶数个奇数

代码实现:
 

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
 
using namespace std;
 
typedef long long ll;
const int maxn = 20;
int a[20];
ll dp[20][20][2];
 
ll rec(int pos, int state, int pre, bool limit, bool lead) 
//pos表示位置,pre为pos位的数,state表示pre同奇偶性的连续的个数个数
{
    if (pos == -1) return (state & 1) != (pre & 1);
    
    if (!limit && !lead && dp[pos][state][pre] != -1) return dp[pos][state][pre];
    int up = limit ? a[pos] : 9;
    ll ans = 0;
    for (int i = 0; i <= up; i++) 
	{
        if (lead)    //处理前导0
		{
            if (i == 0) 
            ans += rec(pos - 1, 0, 0, limit && i == a[pos], true);
            else 
            ans += rec(pos - 1, 1, i & 1, limit && i == a[pos], false);
        }
        else 
        {
            if (i & 1) //选择一个是奇数
			{
			   if (pre & 1)
			    ans += rec(pos - 1, state + 1, i & 1, limit && i == a[pos], false);//pre为奇数直接加
			   else if (!(pre & 1) && (state & 1)) 
                ans += rec(pos - 1, 1, i & 1, limit && i == a[pos], false);//pre为偶数,state为奇数,才转移下一个状态
            }
            else 
            {
                if (!(pre & 1)) 
                ans += rec(pos - 1, state + 1, i & 1, limit && i == a[pos], false);
                else if (pre & 1 && !(state & 1))
				ans += rec(pos - 1, 1, i & 1, limit && i == a[pos], false);
            }
        }
    }
    if (!limit && !lead) dp[pos][state][pre] = ans;
    return ans;
}
 
ll solve(ll x) {
    int pos = 0;
    while (x) {
        a[pos++] = x % 10;
        x /= 10;
    }
    return rec(pos - 1, 0, 0, true, true);
}
 
int main()
{
    int T; 
    scanf("%d", &T);
    ll l, r, flag = 0;
    while (T--) {
        scanf("%lld %lld", &l, &r);
        memset(dp, -1, sizeof(dp));
        printf("Case #%lld: %lld\n", ++flag, solve(r) - solve(l - 1));
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/sdz20172133/article/details/82431229