玲珑学院OJ 1095 Six and One【暴力预处理+剪枝+二分查询】

来源:互联网 发布:济宁淘宝培训 编辑:程序博客网 时间:2024/05/22 17:13

1095 - Six and One

Time Limit:1s Memory Limit:128MByte

Submissions:128Solved:28

DESCRIPTION

Given the integers LL and RR, your task is calculating the count of the integer nn which meet the following conditions:

For instance, 11,66,1616,3636,6161,37213721 are some integers which meet the conditions.

INPUT
The first line contains a positive integerTT, which represents there are TT test cases.The following is test cases. For each test case:The only line contains two positive integerLL and RR.1T105,1LR10101≤T≤105,1≤L≤R≤1010
OUTPUT
For each test case, output in one line, contains one integer, which represents the count of the integers which meet the conditions.
SAMPLE INPUT
4
1 10
16 36
60 70
3720 3722
SAMPLE OUTPUT
2
2
2
1
SOLUTION
“玲珑杯”ACM比赛 Round #10
题目大意:

ai是由6和1组成的数字,需要保证ai<=1e10

现在给你一个区间【l,r】,让你求一共有多少个N,使得L<=N<=R.

这里N表示是由若干个ai相乘得到的,N<=1e10


思路:


1、观察到T很大,明显是要考察O(1)查询或者是O(logn)查询的能力。

二分查询的考察肯定是比较套路的。

所以我萌需要进行预处理答案。


2、估计了一下,长度为1的有6和1,长度为2的有11 16 66 61.那么很明显,预处理出从长度1到长度为10的ai.一共也就是有2046个.

那么我们接下来考虑找寻组合,使得相乘得到的数小于1e10.

我们不妨在纸上简单的处理一些数据,不难发现,当取出来的数的个数大于等于4的时候,情况就变得非常少了。

那么我们Dfs暴力处理,做好剪枝,肯定不会超时。

这里需要注意几点:

①我们最多可能取很多数出来,6^12的得数是小于1e10的.所以我们最多可能要取12个数。

②我们还要对数组进行去重。

③Dfs过程中处理不当可能会出现爆LL的可能,所以我们在相乘两个数的时候,要在长度上进行预估。


3、接下来对于查询,我们找第一个大于l的数出现的位子posl,找第一个小于r的数出现的位子posr,预处理得到的可能的N一共有6w+数,直接枚举找位子肯定是要超时的,所以我们对这6W个数进行排序,然后二分这两个位子,那么ans=posr-posl;


Ac代码:

#include<bits/stdc++.h>using namespace std;#define ll long long intll ans[1000050];ll anstmp[1000050];int cnt;void Dfs(ll nw,int len){    ans[cnt++]=nw;    if(len+1<=10)    Dfs(nw*10+1,len+1);    if(len+1<=10)    Dfs(nw*10+6,len+1);}int lenn(ll a){    int re=0;    while(a)    {        a/=10;        re++;    }    return re;}void Dfs_getnum(ll nw,int ned,int hav,int pos){    if(ned==hav)    {        ans[cnt++]=nw;        return ;    }    if(pos<=2046&&nw*ans[pos]>10000000000||lenn(nw)+lenn(ans[pos])>11)return ;    for(int j=pos;j<=2046;j++)    {        if(nw*ans[j]>10000000000||lenn(nw)+lenn(ans[j])>11)break;        else        {            Dfs_getnum(nw*ans[j],ned,hav+1,j);        }    }}void init(){    cnt=0;    Dfs(1,1);    Dfs(6,1);    sort(ans,ans+cnt);    ll test=1;    for(int i=2;i<=13;i++)    {        for(int j=0;j<cnt;j++)        Dfs_getnum(ans[j],i,1,j);    }    sort(ans,ans+cnt);    for(int i=0;i<cnt;i++)anstmp[i]=ans[i];    int tmpcnt=cnt;    cnt=0;    for(int i=0;i<tmpcnt;i++)    {        if(anstmp[i]==anstmp[i+1])continue;        else        {            ans[cnt++]=anstmp[i];        }    }}int main(){    init();    int t;    scanf("%d",&t);    while(t--)    {        ll tmpl,tmpr;        scanf("%lld%lld",&tmpl,&tmpr);        int ansl=-1;        int l=0;        int r=cnt;        while(r-l>=0)        {            int mid=(l+r)/2;            if(ans[mid]>=tmpl)            {                ansl=mid;                r=mid-1;            }            else l=mid+1;        }        int ansr=-1;        l=0;        r=cnt;        while(r-l>=0)        {            int mid=(l+r)/2;            if(ans[mid]<=tmpr)            {                ansr=mid;                l=mid+1;            }            else r=mid-1;        }        if(ansl==-1||ansr==-1)        {            printf("0\n");        }        else printf("%d\n",ansr-ansl+1);    }}







0 0
原创粉丝点击