题目描述
在中国,很多人都把6和8视为是幸运数字!lxhgww也这样认为,于是他定义自己的“幸运号码”是十进制表示中只包含数字6和8的那些号码,比如68,666,888都是“幸运号码”!但是这种“幸运号码”总是太少了,比如在[1,100]的区间内就只有6个(6,8,66,68,86,88),于是他又定义了一种“近似幸运号码”。lxhgww规定,凡是“幸运号码”的倍数都是“近似幸运号码”,当然,任何的“幸运号码”也都是“近似幸运号码”,比如12,16,666都是“近似幸运号码”。
现在lxhgww想知道在一段闭区间[a, b]内,“近似幸运号码”的个数。
输入输出格式
输入格式:
输入数据是一行,包括2个数字a和b
输出格式:
输出数据是一行,包括1个数字,表示在闭区间[a, b]内“近似幸运号码”的个数
输入输出样例
输入样例#1:
1 10
输出样例#1:
2
说明
对于30%的数据,保证1<=a<=b<=1000000
对于100%的数据,保证1<=a<=b<=10000000000
分析:
题目都说了,幸运号码很少= =
所以暴力幸运数字,然后如果有一个幸运数字是另一个幸运的倍数,这个就是没有用的,然后直接容斥即可。
代码:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#define LL long long
const int maxn=5007;
using namespace std;
LL l,r,cnt,ans;
LL a[maxn];
bool v[maxn];
void ins(LL x)
{
if (x>r) return;
a[++cnt]=x;
}
bool cmp(LL x,LL y)
{
return x>y;
}
LL gcd(LL x,LL y)
{
LL r=x%y;
while (r)
{
x=y;
y=r;
r=x%y;
}
return y;
}
LL lcm(LL x,LL y)
{
LL s=gcd(x,y);
double tmp=(double)x/s*y;
if (tmp>r) return r+1;
return (x*y)/s;
}
void dfs(int x,int k,LL d)
{
if (d>r) return;
if (x>cnt)
{
if (d==1) return;
ans+=k*(r/d-(l-1)/d);
return;
}
if (v[x]) dfs(x+1,k,d);
else
{
dfs(x+1,k,d);
dfs(x+1,-k,lcm(a[x],d));
}
}
int main()
{
scanf("%lld%lld",&l,&r);
a[1]=6; a[2]=8;
cnt=2;
for (int i=1;i<=cnt;i++)
{
ins(a[i]*10+6);
ins(a[i]*10+8);
}
sort(a+1,a+cnt+1,cmp);
for (int i=1;i<=cnt;i++)
{
for (int j=1;j<i;j++)
{
if (a[i]%a[j]==0)
{
v[i]=1;
break;
}
}
}
dfs(1,-1,1);
printf("%lld",ans);
}