Description
Cirno发现了一种baka数,这种数呢只含有2和⑨两种数字
现在Cirno想知道一个区间中有多少个数能被baka数整除
但是Cirno这么天才的妖精才不屑去数啦
只能依靠聪明的你咯。
Input
一行正整数L R
( 1 < L < R < 10^9)
Output
一个正整数,代表所求的答案
Solution
⑨题
容斥原理。
eg:被3和5整除的有n/3+n/5-n/15个
易知对于n中能被
a
1
−
a
m
a_1-a_m
a1−am整除的个数为
∑
n
/
奇
数
个
a
i
公
倍
数
−
∑
n
/
偶
数
个
a
i
公
倍
数
\sum n/奇数个a_i公倍数-\sum n/偶数个a_i公倍数
∑n/奇数个ai公倍数−∑n/偶数个ai公倍数
直接深搜模拟这个过程 即每个选与不选
先预处理出1~1e9中的所有baka数
去掉倍数关系的 只留下最小且互不为倍数关系的baka数
对于>n/3的baka数并不能预其他数求lcm 所以可以直接算
然后把baka数从大到小排列,可以更快地使lcm超过r以剪枝
跟洛谷P2567 [SCOI2010]幸运数字是一样的。
Code
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll f[12][10010];
int a[10010],cnt;
ll l,r,ans;
ll gcd(ll a,ll b){
return a?gcd(b%a,a):b;
}
void dfs(int x,ll v,int n){
if(x>cnt||v>r) {
if(n){
if(n&1) ans+=r/v-(l-1)/v;
else ans-=r/v-(l-1)/v;
}
return;
}
if(v*1.0*a[x]/gcd(a[x],v)<=r)
dfs(x+1,v*a[x]/gcd(a[x],v),n+1);
dfs(x+1,v,n);
}
bool cmp(int a,int b){
return a>b;
}
int main(){
f[0][0]=1;
scanf("%lld%lld",&l,&r);
for(int i=1;i<=10;i++)
for(int j=1;j<=f[i-1][0];j++){
if(f[i-1][j]*10+2<=r) a[++cnt]=f[i][++f[i][0]]=f[i-1][j]*10+2;
if(f[i-1][j]*10+9<=r) a[++cnt]=f[i][++f[i][0]]=f[i-1][j]*10+9;
}
int tot=0;
for(int i=1;i<=cnt;i++){
bool flag=1;
for(int k=1;k<=tot;k++){
if(a[i]%a[k]==0){
flag=false;
break;
}
}
if(flag){
if(a[i]<=r/2) a[++tot]=a[i];
else ans+=r/a[i]-(l-1)/a[i];
}
}
cnt=tot;
sort(a+1,a+cnt+1,cmp);
dfs(1,1,0);
printf("%lld",ans);
}