题意:给你一个区间,问区间内有多少个数字内只包含6,8的数字和其倍数。
和2393巨像,所以也是容斥原理(好像很显然)。
只有6,8的数字有2000多个,然后互质的搞搞就只有10几个了,这就很zici。
问题是怎么样处理其倍数,我们搜索一下,记录当前遍历到第几个幸运数,选择了多少个幸运数,已选择的幸运数的lcm是多少。
明显,近似幸运数是幸运数的lcm。而且,一个数以及其倍数在l,r中出现的次数=r/x-(l-1)/x,这样子我们就可以容斥原理xjb统计统计就好。
注意lcm不能比r大,不然会炸ll,加个剪枝就好。
由于前天晚上改了半天不知道哪里挂了一怒之下对着oxer的代码来了一发= =
#include<cstdio>
#include<cstring>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
const int N=1e5+5;
int n,m;
typedef long long ll;
ll q[N],l,r;
int tot;
bool vis[N];
ll ans;
inline void dfs(ll x)
{
if (x>r)return;
if (x)q[++tot]=x;
dfs(x*10+6),dfs(x*10+8);
}
bool cmp(ll a,ll b)
{
return a>b;
}
ll gcd(ll a,ll b)
{
if (a%b==0)return b;
else return gcd(b,a%b);
}
inline void dfs1(int x,int d,ll lcm)
{
if (x==tot)return;
x++;
dfs1(x,d,lcm);
d++;
if(vis[x])return;
lcm=lcm*q[x]/gcd(lcm,q[x]);
if (lcm<=0||lcm>r)return;
if (d&1)ans+=r/lcm-(l-1)/lcm;
else ans-=r/lcm-(l-1)/lcm;
dfs1(x,d,lcm);
}
int main()
{
scanf("%lld%lld",&l,&r);
dfs(0);
sort(q+1,q+tot+1,cmp);
fo(i,1,tot)
fo(j,i+1,tot)
if (q[i]%q[j]==0)vis[i]=1;
dfs1(0,0,1);
printf("%lld\n",ans);
}