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