[HDU]2089不要62
http://acm.hdu.edu.cn/showproblem.php?pid=2089
这道题跟Bomb(http://www.cnblogs.com/sjy123/p/3247731.html)基本一样,不过多了一个不要包含4的条件,因为数值的范围不大,本来这道题完全可以暴力完成的,不过既然刚学了数位DP,就用一用吧。
------------------------------------------------分割线-------------------------------------------------
状态转移方程
dp[i][0]=dp[i-1][0]*9-dp[i-1][1]; //不含62和4
dp[i][1]=dp[i-1][0]; //不含62和4,但2结尾
dp[i][2]=dp[i-1][2]*10+dp[i-1][1]+dp[i-1][0]; //含62和4
不解释了,得出的过程了Bomb基本一样
----------------------------------------------分割线------------------------------------------------
#include"stdio.h" #include"stdlib.h" #include"string.h" int dp[20][3]; int a[20]; int fun(int len) { int i,flag=0,sum=0,last=0; //last表示一轮的位,即这轮的高一位 for(i=len;i>=1;i--) { sum+=dp[i-1][2]*a[i]; if(flag) sum+=dp[i-1][0]*a[i]; if(!flag&&a[i]>6) //本轮最高位大于6,需要加上低一位以2开头的数 sum+=dp[i-1][1]; if(!flag&&last==6&&a[i]>2) //上一轮最高位等于6,要加上这轮的以2开头的个数 sum+=dp[i][1]; if(!flag&&a[i]>4) //本轮最高位大于4,所以上一轮不含的数,这轮加上去 sum+=dp[i-1][0]; if((last==6&&a[i]==2)||a[i]==4) flag=1; last=a[i]; } return sum; } int main() { int i,len,n,m,sum1,sum2,sum,t; memset(dp,0,sizeof(dp)); //初始化 dp[0][0]=1; for(i=1;i<21;i++) //算出彼此关系,下面计算时,直接调用 { dp[i][0]=dp[i-1][0]*9-dp[i-1][1]; //不含62和4 dp[i][1]=dp[i-1][0]; //不含62和4,但2结尾 dp[i][2]=dp[i-1][2]*10+dp[i-1][1]+dp[i-1][0]; //含62和4 } while(scanf("%d%d",&n,&m)!=EOF) { if(n==0&&m==0) break; sum1=0; t=m-n+1; //n到m区间的总个数 len=0; memset(a,0,sizeof(a)); while(n) { a[++len]=n%10; n=n/10; } a[len+1]=0; sum1=fun(len); sum2=0; len=0; memset(a,0,sizeof(a)); m++; while(m) { a[++len]=m%10; m=m/10; } a[len+1]=0; sum2=fun(len); printf("%d\n",t-(sum2-sum1)); } // system("pause"); }
这面是暴力的作法,百度的。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<stdio.h> using namespace std; int a[1000001]; int main() { int n,m; a[0]=1; int i; for(i=1;i<=1000000;i++) { if(i%10!=4&&i%100!=62&&a[i/10]==1) a[i]=1; else a[i]=0; } while(cin>>n>>m,n||m) { int count=0; for(int i=n;i<=m;i++) { if(a[i]==1) count++; } cout<<count<<endl; } }