您的位置:首页 > 产品设计 > UI/UE

UESTC 1137 邱老师选妹子

2016-04-15 11:05 344 查看


邱老师选妹子


Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others)


Submit 
Status

邱老师长得帅这是人尽皆知,于是追他的妹子就会很多。
但是你知道,邱老师是一个很专一的人,所以他心里面只能有一个人。
于是他决定从追他的众多妹子里挑选一个出来。于是酱神给邱老师出来一个主意,已知有一些妹子,恰好可以给她们从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).en
a77a
d(); ++ 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: