【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;
}
posted @ 2020-10-09 10:31  stoorz  阅读(145)  评论(0编辑  收藏  举报