UESTC 1137 邱老师选妹子

时间:2022-12-16 12:08:29

邱老师选妹子

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