您的位置:首页 > 其它

HDU 2089 不要62

2013-12-14 14:50 197 查看
题意:定义一个数如果含有数字4,或者出现“62”则为不吉利数,否则为吉利数。比如242,8262均不吉利, 但22682吉利。求区间[a, b]中有多少个数为吉利数。

   0 < a <= b < 10^6。

解法:问题即是求对于任意的x < 10^6,求[0, x)内有多少个吉利数。

   设d[i][0]表示长度为i的数(首位为0也算,比如0020长度为4)中,首位不为2且吉利的数的个数。

    d[i][1]表示长度为i的数中,首位为2且吉利的数的个数。

    d[i][2]表示长度为i的数中,不吉利的数的个数。

   首先预处理出d[8][3]。

   然后从对x从高位到低位遍历,比如x为23476,遍历到4时,求出所有小于23400的,前缀为23的不吉利数。详见代码。

tag:数位DP, 基础题

/*
* Author:  Plumrain
* Created Time:  2013-12-14 13:40
* File Name: DP-HDU-2089.cpp
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

#define CLR(x) memset(x, 0, sizeof(x))

int s[20], d[10][3];

int gao(int x)
{
int ret = x + 1;
CLR (s);
int len = 0;
while (x){
s[len++] = x % 10;
x /= 10;
}
s[len] = 0;

bool flag = 0;
for (int i = len-1; i >= 0; -- i){
ret -= s[i] * d[i][2];
if (flag) ret -= s[i] * (d[i][0] + d[i][1]);
else{
if (s[i] > 6) ret -= d[i][1];
if (s[i] > 4) ret -= d[i][0] + d[i][1];
if (s[i+1] == 6 && s[i] > 2) ret -= d[i][0] + d[i][1];
}

if ((s[i+1] == 6 && s[i] == 2) || s[i] == 4) flag = 1;
}
return ret;
}

int main()
{
CLR (d);
d[0][0] = 1;
for (int i = 1; i < 10; ++ i){
d[i][0] = 8 * (d[i-1][0] + d[i-1][1]) - d[i-1][1];
d[i][1] = d[i-1][1] + d[i-1][0];
d[i][2] = d[i-1][0] + 2*d[i-1][1] + 10*d[i-1][2];
}

int n, m;
while (scanf ("%d%d", &n, &m) != EOF){
if (!n && !m) break;
printf ("%d\n", gao(m+1) - gao(n));
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: