HDU 5898 - odd-even number

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


題意:奇偶數就是偶數的連續個數有奇數個,奇數的連續個數有偶數個,給出一個區間,求這個區間總共有多少個odd-even number。


一道數位DP題,用ans[i][j][k]表示前 i 位,前一位是 j,奇數或偶數有 k。具體註釋看代碼。

#include <cstdio>

long long ans[20][11][20];
//第i位,前一位是j,奇數或偶數有k
int num[20];//把數字拆開

//lead表示有無前導0
//limit表示是否是上限
long long solve(int pos, int state, int n, bool lead, bool limit)
{
    //只有一個數的情況
    if (pos == -1 && (state + n) % 2 == 1)
        return 1;
    if (pos == -1 && (state + n) % 2 == 0)
        return 0;

    if (!lead && !limit && ans[pos][state][n] != -1)
        return ans[pos][state][n];

    int up = limit ? num[pos] : 9;
    long long ret = 0;
    if (lead)
    {
        for (int i = 0; i <= up; ++i)
            ret += solve(pos-1, i, 1, lead && i == 0, limit && i == num[pos]);
    }
    else if ((state + n) % 2 == 1)//奇數
    {
        for (int i = 0; i <= up; ++i)
        {
            if ((i + state) % 2 == 0)//奇數後是奇數
                ret += solve(pos-1, i, n+1, lead && i == 0, limit && i == num[pos]);
            else//奇數後是偶數
                ret += solve(pos-1, i, 1, lead && i == 0, limit && i == num[pos]);
        }
    }
    else
    {
        for (int i = 0; i <= up; ++i)
        {
            if ((i + state) % 2 == 0)
                ret += solve(pos-1, i, n+1, lead && i == 0, limit && i == num[pos]);
        }
    }
    if (!limit && !lead)
        ans[pos][state][n] = ret;
    return ret;
}

int main()
{
    int T;
    long long left, right;

    for (int i = 0; i < 20; ++i)
        for (int j = 0; j < 11; ++j)
            for (int k = 0; k < 20; ++k)
                ans[i][j][k] = -1;

    scanf("%d", &T);
    for (int icase = 1; icase <= T; ++icase)
    {
        long long ans_left, ans_right;
        scanf("%lld %lld", &left, &right);
        left--;

        int pos = 0;
        num[0] = 0;
        while (left != 0)
        {
            num[pos++] = left % 10;
            left /= 10;
        }
        //printf("left ok\n");
        ans_left = solve(pos-1, 10, 1, true, true);
        //printf("solve left ok\n");

        pos = 0;
        num[0] = 0;
        while (right != 0)
        {
            num[pos++] = right % 10;
            right /= 10;
        }
        //printf("right ok\n");
        ans_right = solve(pos-1, 10, 1, true, true);
        //printf("solve right ok\n");

        printf("Case #%d: %lld\n", icase, ans_right - ans_left);
    }
    return 0;
}
PS.看到odd-even number想起大倉明日香的《prime number~君と出會える日~》

也許回過頭來再看櫻花莊裏發生的故事只會感覺自己那麼幼稚、愚笨,但是唯一不變和讓自己感覺當初幼稚愚笨的原因,則是在幼稚和愚笨中的努力汗水淚水。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章