hdu 2089 不要62 (数位DP)

不要62

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 31185    Accepted Submission(s): 11017


Problem Description
杭州人称那些傻乎乎粘嗒嗒的人为62(音:laoer)。
杭州交通管理局经常会扩充一些的士车牌照,新近出来一个好消息,以后上牌照,不再含有不吉利的数字了,这样一来,就可以消除个别的士司机和乘客的心理障碍,更安全地服务大众。
不吉利的数字为所有含有4或62的号码。例如:
62315 73418 88914
都属于不吉利号码。但是,61152虽然含有6和2,但不是62连号,所以不属于不吉利数字之列。
你的任务是,对于每次给出的一个牌照区间号,推断出交管局今次又要实际上给多少辆新的士车上牌照了。
 

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

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

Sample Input
   
   
   
   
1 100 0 0
 

Sample Output
   
   
   
   
80
 

Author
qianneng
 

Source
迎接新学期——超级Easy版热身赛
 

Recommend
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);    
    }     
}  




你可能感兴趣的:(hdu 2089 不要62 (数位DP))