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
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~君と出会える日~》
也许回过头来再看樱花庄里发生的故事只会感觉自己那么幼稚、愚笨,但是唯一不变和让自己感觉当初幼稚愚笨的原因,则是在幼稚和愚笨中的努力汗水泪水。