HRBUST 1365 预处理+二分+?

来源:互联网 发布:主播招聘知乎 编辑:程序博客网 时间:2024/05/02 00:32

HRBUST   1365

Unlucky Number III

一所有数字只包含7或者4被称为Unlucky Number,比如4,7,44,77是,而32,37..不是

定义f(x)=不小于数字x的最小的Unlucky Number,即>=x的最小的Unlucky Number

输入包括T ,st,ed;数据组数,起点,终点。(1 ≤ st ≤ ed ≤ 109).

求 x =st 到 ed 的f(x)的和;

Sample Input
2
3 6
4 4


Sample Output
22
4


Hint
In the first sample: f (3) + f (4) + f (5) + f (6) = 4 + 4 + 7 + 7 = 22

In the second sample: f (4) = 4


首先需要构造出所有可能的Unlucky Number,

这个序列前几项为4,7,44,47,74,以队列的顺序每次取之前没有考虑过的往后面+4 +7就可以,加到长度>9就可以终止了

4+4->44

4+7->47

7+4->74.....

 st,ed <10^9,st枚举到ed肯定要TLE的.

由于Unlucky Number的序列是单调的,所以可以二分找到num[st],起点对应的Unlucky Number,

然后一个now=当前统计的数字x的下标,ss=当前位置所对应的Unlucky Number的下标

如果num[ss]<=ed;当前位置所对应的Unlucky Number的下标没有超过终点,

    那么当前位置now到当前位置所对应的Unlucky Number之间的数字x的f(x)都是num[ss];

否则   当前位置now到终点之间的数字x的f(x)都是num[ss];


#include<stdio.h>#include<map>using namespace std;long long num[9999]={0,4,7};int main(){    int tot=3,tp=2,i=1;    while(1){        for(;i<=tp;i++){            num[tot++]=num[i]*10+4;            num[tot++]=num[i]*10+7;            if(i>1500)break;        }        tp=tot;        if(tot>1500)break;    }    int t,st,ed,mid,ss,dd;    scanf("%d",&t);    while(t--){        scanf("%d %d",&st,&ed);        long long ans=0;        int left=1,right=1500;        while(right>=left){            mid=(left+right)/2;            if(num[mid]<st)left=mid+1;            else right=mid-1;        }        ss=left;        int now=st;        while(1){        if(num[ss]<=ed)ans+=(num[ss]-now+1)*num[ss];        else {            ans+=(ed-now+1)*num[ss];            break;        }        now=num[ss]+1;        ss++;        }        printf("%lld\n",ans);    }    return 0;}



原创粉丝点击