【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

题解:首先把所有符合条件的数与处理出来,然后去掉这些倍数。

然后我们边搜索边容斥即可,因为几个数最大公约数大于R就没有意义了,所以这样剪枝会很快。

代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define N 2010
using namespace std;
long long a[N],b[N],vis[N],ans,l,r;
long long gcd(long long a,long long b){return b?gcd(b,a%b):a;}
void pro(long long x){if (x>r) return;a[++a[0]]=x;pro(x*10+2);pro(x*10+9);} 
void dfs(int p,int f,long long v){
    if(!b[p]){if(v!=1)ans+=(r/v-(l-1)/v)*f;return;}
    dfs(p+1,f,v);
    long long temp=v*b[p]/gcd(v,b[p]);if(temp>r) return;
    dfs(p+1,-f,temp);
}
int main(){
  scanf("%lld%lld",&l,&r);pro(2);pro(9);sort(a+1,a+a[0]+1); 
  for (int i=1;i<a[0];i++)
   for (int j=i+1;j<=a[0];j++)
     if (a[j]%a[i]==0) vis[j]=1;
  for (int i=1;i<=a[0];i++) if (!vis[i]) b[++b[0]]=a[i]; 
  dfs(1,-1,1);
  cout<<ans<<endl;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值