您的位置:首页 > 其它

hdu 2089 不要62 (数位DP)

2016-04-24 09:13 246 查看

不要62

Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 31185 Accepted Submission(s): 11017



[align=left]Problem Description[/align]
杭州人称那些傻乎乎粘嗒嗒的人为62(音:laoer)。

杭州交通管理局经常会扩充一些的士车牌照,新近出来一个好消息,以后上牌照,不再含有不吉利的数字了,这样一来,就可以消除个别的士司机和乘客的心理障碍,更安全地服务大众。

不吉利的数字为所有含有4或62的号码。例如:

62315 73418 88914

都属于不吉利号码。但是,61152虽然含有6和2,但不是62连号,所以不属于不吉利数字之列。

你的任务是,对于每次给出的一个牌照区间号,推断出交管局今次又要实际上给多少辆新的士车上牌照了。

[align=left]Input[/align]
输入的都是整数对n、m(0<n≤m<1000000),如果遇到都是0的整数对,则输入结束。

[align=left]Output[/align]
对于每个整数对,输出一个不含有不吉利数字的统计个数,该数值占一行位置。

[align=left]Sample Input[/align]

1 100
0 0


[align=left]Sample Output[/align]

80


[align=left]Author[/align]
qianneng

[align=left]Source[/align]
迎接新学期——超级Easy版热身赛

[align=left]Recommend[/align]
lcy | We have carefully selected several similar problems for you: 2094 2090 2091 2093 2092

Statistic | Submit | Discuss
|
Note

题解:数位DP

具体过程参见代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<iostream>
using namespace std;
int n,m,cnt,num[10];
int dp[12][12];
int sqr(int x,int y)
{
int t=1;
if (y==0) return 1;
for (int i=1;i<=y;i++)
t=t*10;
return t;
}
int sqr1(int x,int y)
{
int t=0;
for (int i=1;i<=y;i++)
t=t*10+9;
return t;
}
void init()
{
dp[0][0]=1;
for (int i=1;i<=7;i++)
{
dp[i][0]=9*dp[i-1][0]-dp[i-1][1]; //dp[i][0] 表示位数不超过i的数字中不含不吉利的数字个数
dp[i][1]=dp[i-1][0];//dp[i][1] 表示位数不超过i的数字中不含不吉利数字,且最高位为2的个数
dp[i][2]=sqr1(9,i)+1-dp[i][0];//dp[i][2] 表示位数不超过i的数字中含不吉利数字的个数
}
}
int solve(int x)
{
int ans=0,k=x;
cnt=0; int tot=0;
while (x)  //把数字按位分解
{
num[++tot]=x%10;
x/=10;
}
bool f=false;
num[0]=0;  num[tot+1]=0;
for (int i=tot;i>=1;i--) //计算的时候,把数拆分,例如43,拆成1-39,40-43来计算
{
if (f) {
continue;
}
if (num[i]<4)  ans+=(num[i])*dp[i-1][2]; //当前位小于4,直接计算0-(num[i]-1)
else
if (num[i]>4)
ans+=sqr(10,i-1)+(num[i]-1)*dp[i-1][2];//当前位可以是0-(num[i]-1),把4的情况单独提出来计算 ,sqr(10,i-1)就是计算当前位上4的个数

else
{
ans+=(num[i])*dp[i-1][2];//计算当前位是0-3的个数
ans+=k%sqr(10,i-1)+1;//计算当前位是4时,剩下的位置有多少中填法
f=true;//因为如果当前位是4,剩下的位置无论怎么填都是不合法的,打个标记,避免重复计算
}
if (num[i+1]==6)//计算含62的情况
{
if (num[i]>2)  ans+=dp[i][1];
else if (num[i]==2)  ans+=k%sqr(10,i-1)+1;
}
else
if (num[i+1]>6)  ans+=dp[i][1];
if (num[i+1]==6&&num[i]==2) //因为如果当前位是2,前一位是6,剩下的位置无论怎么填都是不合法的,打个标记,避免重复计算
f=true;
}
return ans;
}
int main()
{
init();
while(scanf("%d%d",&n,&m))
{
if (!n&&!m) break;
int t=m-n+1-solve(m)+solve(n-1);
printf("%d\n",t);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: