【hdu2089】不要62 数位dp
题目描述
求 $[n,m]$ 内不包含数位串 “4” 和 “62” 的数的个数。
输入
输入的都是整数对n、m(0<n≤m<1000000),如果遇到都是0的整数对,则输入结束。
输出
对于每个整数对,输出一个不含有不吉利数字的统计个数,该数值占一行位置。
样例输入
1 100
0 0
样例输出
80
题解
数位dp
设 $f[i][j]$ 表示 $i$ 位数,最高位为 $j$ ,且不出现数位串 “4” 和 “62” 的数的个数。
那么直接枚举上一位,根据是否构成非法串进行转移。
然后对于每组询问转化为 $[1,a)$ 的区间相减,每个区间进行数位dp,先计算位数不满的,再从高位到低位枚举,当前位如果小于 $a$ 的这一位则一定满足区间条件。如果这一位和上一位不构成 “62” 则统计到答案中。
注意当上一位与当前位组成“62”时及时跳出循环。
(貌似本题暴力可过?...)
#include <cstdio>
int f[8][10] , b[8];
void init()
{
	int i , j , k;
	f[0][0] = b[0] = 1;
	for(i = 1 ; i < 8 ; i ++ )
	{
		b[i] = b[i - 1] * 10;
		for(j = 0 ; j < 10 ; j ++ )
			for(k = 0 ; k < 10 ; k ++ )
				if(j != 4 && !(j == 6 && k == 2))
					f[i][j] += f[i - 1][k];
	}
}
int calc(int n)
{
	int i , j , di = 1 , last = 0 , now , ans = 0;
	for(i = 1 ; b[i] <= n ; i ++ )
		for(j = 1 ; j < 10 ; j ++ )
			ans += f[i][j];
	for( ; i ; i -- )
	{
		now = n / b[i - 1] % 10;
		for(j = di ; j < now ; j ++ )
			if(!(last == 6 && j == 2))
				ans += f[i][j];
		if(now == 4 || (last == 6 && now == 2)) break;
		di = 0 , last = now;
	}
	return ans;
}
int main()
{
	init();
	int n , m;
	while(~scanf("%d%d" , &n , &m) && !(n == 0 && m == 0))
		printf("%d\n" , calc(m + 1) - calc(n));
	return 0;
}
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号