邱老师选妹子
Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others)
邱老师长得帅这是人尽皆知,于是追他的妹子就会很多。
但是你知道,邱老师是一个很专一的人,所以他心里面只能有一个人。
于是他决定从追他的众多妹子里挑选一个出来。于是酱神给邱老师出来一个主意,已知有一些妹子,恰好可以给她们从l到r排号,使得每一个妹子有单独
的数字,而正好有r-l+1个妹子。酱神说,我们不能要运气不好的女孩,而酱神又给了两个数字62和4,如果妹子的排号里面有62(必须是连续的)或4,那么
就排除他现在给你l和r,问有多少妹子可以有幸在第一轮留下。
Input
输入的都是整数对l、r(0<l≤r<1000000),如果遇到都是0的整数对,则输入结束。
Output
每组数据输出占一行,对于每个l和r 输出有多少个妹子可以在第一轮不被排除
杭电原题,不要62。
数据量比较小,可以直接暴力,这里就不贴暴力了,用数位DP做一下.
dp[i][0]表示长度小于等于i,符合题意的数的个数。
dp[i][1]表示长度为i,首位为2的个数。
那么就有转移方程:
dp[i][0]=(dp[i-1][0]-dp[i-1][1])*9+8*dp[i-1][1]=dp[i-1][0]*9-dp[i-1][1]
然后给定了一个abcd
计算1-abcd有多少个的时候,a*dp[3][0]+b*dp[2][0]+c*dp[1][0]+d*dp[0][0]
但是如果某一位是4 或者超过4 或者出现了62那么就要处理一下。
因为处理的时候对于一个n没有把自己合不合法考虑进去,所以输入left和right的时候计算cal(right+1)-cal(left)
代码:
//************************************************************************// //*Author : Handsome How *// //************************************************************************// //#pragma comment(linker, "/STA CK:1024000000,1024000000") #pragma warning(disable:4996) #include <vector> #include <map> #include <set> #include <deque> #include <queue> #include <stack> #include <algorithm> #include <sstream> #include <iostream> #include <cstdio> #include <cmath> #include <cstdlib> #include <cstring> #include <ctime> #include <cassert> #if defined(_MSC_VER) || __cplusplus > 199711L #define aut(r,v) auto r = (v) #else #define aut(r,v) __typeof(v) r = (v) #endif #define each(it,o) for(aut(it, (o).begin()); it != (o).end(); ++ it) #define fur(i,a,b) for(int i=(a);i<=(b);i++) #define furr(i,a,b) for(int i=(a);i>=(b);i--) #define cl(a) memset((a),0,sizeof(a)) #define mp make_pair #define pb push_back #define fi first #define se second #define sc(x) scanf("%d",&x) using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair <int, int> pii; const int inf=0x3f3f3f3f; const double eps=1e-8; const int mod=1000000007; const double pi=acos(-1); inline void gn(long long&x){ int sg=1;char c;while(((c=getchar())<'0'||c>'9')&&c!='-');c=='-'?(sg=-1,x=0):(x=c-'0'); while((c=getchar())>='0'&&c<='9')x=x*10+c-'0';x*=sg; } inline void gn(int&x){long long t;gn(t);x=t;} inline void gn(unsigned long long&x){long long t;gn(t);x=t;} inline void gn(double&x){double t;scanf("%lf",&t);x=t;} inline void gn(long double&x){double t;scanf("%lf",&t);x=t;} //---------------------------------------------------------- int dp[10][2]; //dp[i][0] 满足条件的长度小于=i的数 //dp[i][1] 满足条件的2开头的长度小于=i的数 void init(){ cl(dp); dp[0][0]=1; fur(i,1,9){ dp[i][0]=dp[i-1][0]*9-dp[i-1][1]; dp[i][1]=dp[i-1][0]; } } int calc(int n){ if(n==1)return 1; int k = n; int numb[10]; int t = 0; bool okn = false; while(n){ numb[++t] = n%10; n/=10; } int ans = 0; furr(i,t,1){ if(numb[i+1]==4||(numb[i+1]==2)&&numb[i+2]==6)break; if(numb[i]==0)continue; if(numb[i]>=7)ans=ans+(numb[i]-1)*dp[i-1][0]-dp[i-1][1]; if(numb[i]<=4)ans=ans+numb[i]*dp[i-1][0]; if(numb[i]==5||numb[i]==6)ans=ans+(numb[i]-1)*dp[i-1][0]; if(numb[i+1]==6&&numb[i]>=3)ans=ans-dp[i][1]; } return ans; } int main() { //freopen("E:\\data.in", "r", stdin); ios :: sync_with_stdio(false); init(); int l,r; while(scanf("%d %d",&l,&r)){ if(l>r){ printf("0\n"); continue; } if(!l&&!r)return 0; int ll=calc(l); int rr=calc(r+1); int ans=rr-ll; printf("%d\n",ans); } return 0; }