BZOJ2393 Cirno的完美算数教室

Description

~Cirno发现了一种baka数,这种数呢~只含有2和⑨两种数字~~
现在Cirno想知道~一个区间中~~有多少个数能被baka数整除~
但是Cirno这么天才的妖精才不屑去数啦
只能依靠聪明的你咯。
 
 

Input

一行正整数L R
( 1 < L < R < 10^10)
 

Output

一个正整数,代表所求的答案
 

Sample Input

1 100

Sample Output

58
 
题解:搜索+容斥原理
求一个区间内的某些数倍数的个数。

预处理所有的baka数,有2000多个,然后把某些baka数的倍数去掉后有400多个baka数,然后

加一个剪枝,当lcm>r时不搜索,能过。

代码:

 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
using namespace std;

LL l,r,p,q,ans,a[1020],b[1020],vis[1020];

void get_baka(LL x){//这里没开LL,卡了一个小时。我是不是没救了QAQ 
    if(x>r)return;
    if(x)a[++p]=x;
    get_baka(x*10+2);get_baka(x*10+9);
}

LL gcd(LL i,LL j){
    return j==0?i:gcd(j,i%j);
}

void dfs(int now,int cnt,LL lcm){
    if(now==q+1){
        if(cnt&1)ans=ans+r/lcm-(l-1)/lcm;
        else if(cnt)ans=ans-r/lcm+(l-1)/lcm;
        return;
    }
    dfs(now+1,cnt,lcm);
    LL vv=(b[now]*lcm)/gcd(lcm,b[now]);
    if(vv<=r)dfs(now+1,cnt+1,vv);
}

int main(){
    scanf("%lld%lld",&l,&r);
    get_baka(0);
    sort(a+1,a+p+1);
    for(int i=1;i<=p;i++){
        if(!vis[i]){
            b[++q]=a[i];
            for(int j=i+1;j<=p;j++)
             if(a[j]%a[i]==0)vis[j]=true;
        }
    }
    dfs(1,0,1);
    cout<<ans<<endl;
    return 0;
}

 

 

posted @ 2017-10-09 21:40  ANhour  阅读(218)  评论(0编辑  收藏  举报