HDU 2089 不要62
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 2089 不要62相关的知识,希望对你有一定的参考价值。
刚学的数位DP。
dp[i][j]表示,长度为i的数字,并且最高位为j的情况下的吉利的数字有几个
很显然dp[i][j]是由dp[i-1][0,1,2,3,.....9]推导而来的
处理出dp数组之后,我们能在o(1)效率内得到以某个数字开头的数字有几个
举个例子:
假设我们现在需要计算的是235--990000之间有几个吉利的数字
我们很快能得到200--999999之间的数字有几个,dp数组已经预处理好了,累加即可
剩下的就是把200--234之间的吉利数字个数乙级990001--999999之间的吉利数字个数删除,这一步暴力即可
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> #include <queue> #include <vector> #include <cmath> #include <map> #include <string> using namespace std; //dp[i][j]表示,长度为i的数字,并且最高位为j的情况下的吉利数字的个数 int dp[15][15]; int p[15]; int tot; int a,b; bool f(int x) { tot=0; while(x) { p[tot++]=x%10; x=x/10; } for(int i=0; i<tot/2; i++) swap(p[i],p[tot-i-1]); for(int i=0; i<tot; i++) if(p[i]==4) return 1; //是不吉利数 for(int i=1; i<tot; i++) if(p[i-1]==6&&p[i]==2) return 1; //是不吉利数 return 0;//不是不吉利数 } void init() { memset(dp,0,sizeof dp); for(int i=0; i<=9; i++) dp[1][i]=1; dp[1][4]=0; for(int i=2; i<=7; i++) { for(int j=0; j<=9; j++) { if(j==4) //这一位是4,那么GG { dp[i][j]=0; continue; } for(int k=0; k<=9; k++) //从第i-1位的0--9推导过来 { if(j==6&&k==2) continue;//这一位是6,上一位是2 GG else dp[i][j]=dp[i][j]+dp[i-1][k]; //个数累加上去 } } } } int main() { init(); while(~scanf("%d%d",&a,&b)) { if(!a&&!b) break; int tmp; int lena=0,firsta; int lenb=0,firstb; tmp=a; while(tmp) lena=lena+1, firsta=tmp%10, tmp=tmp/10; tmp=b; while(tmp) lenb=lenb+1, firstb=tmp%10, tmp=tmp/10; int ans=0; bool fail=0; // printf("---%d %d\n",lena,firsta); // printf("---%d %d\n",lenb,firstb); for(int i=lena; i<=lenb; i++) { if(fail==0) { if(i==lena) for(int j=firsta; j<=9; j++) { if(i==lenb&&j>firstb) {fail=1; break;} ans=ans+dp[i][j]; } else if(i==lenb) for(int j=1; j<=firstb; j++) { if(i==lenb&&j>firstb) {fail=1; break;} ans=ans+dp[i][j]; } else for(int j=1; j<=9; j++) { if(i==lenb&&j>firstb) {fail=1; break;} ans=ans+dp[i][j]; } } } for(int i=0; i<lena-1; i++) firsta=firsta*10; for(int i=0; i<lenb-1; i++) firstb=firstb*10+9; for(int i=firsta; i<=a-1; i++) if(f(i)==0) ans--; for(int i=b+1; i<=firstb; i++) if(f(i)==0) ans--; printf("%d\n",ans); } return 0; }
以上是关于HDU 2089 不要62的主要内容,如果未能解决你的问题,请参考以下文章