【HDU 5898】odd-even number
题目
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5898
求 \([l,r]\) 内有多少个数字满足该数字连续的偶数有奇数个,连续的奇数有偶数个。
思路
考虑数位 dp。设 \(f[i][j][0/1]\) 表示现在处理到第 \(i\) 位,有连续 \(j\) 个奇数 / 偶数的方案数。
转移的时候枚举这一位选择的数即可。注意最后一位时要判断最后连续的几个数是否合法。
代码
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N=20;
int Q,bit[N];
ll ql,qr,f[N][N][2];
// 第 x 位,有连续 cnt 个奇偶性位 num 的数,是否要有上界要求,是否有前导零。
ll dfs(int x,int cnt,int num,bool flag,bool lead)
{
if (!x) return (cnt&1)^num;
if (!flag && !lead && f[x][cnt][num]!=-1) return f[x][cnt][num];
ll ret=0;
int up=flag?bit[x]:9;
for (int i=0;i<=up;i++)
{
if (!i && lead)
ret+=dfs(x-1,0,1,0,1);
else
{
if ((i&1)==num)
ret+=dfs(x-1,cnt+1,num,flag&(i==bit[x]),0);
if ((i&1)!=num && (cnt&1)!=num)
ret+=dfs(x-1,1,num^1,flag&(i==bit[x]),0);
}
}
if (!flag && !lead) f[x][cnt][num]=ret;
return ret;
}
ll solve(ll num)
{
memset(f,-1,sizeof(f));
int cnt=0;
for (;num;num/=10)
bit[++cnt]=num%10;
return dfs(cnt,0,1,1,1);
}
int main()
{
scanf("%d",&Q);
for (int i=1;i<=Q;i++)
{
scanf("%lld%lld",&ql,&qr);
printf("Case #%d: %lld\n",i,solve(qr)-solve(ql-1));
}
return 0;
}