题目描述:
雾。
题目分析:
先预处理出仅含6或8的数
然后用容斥原理求倍数
要从大到小搜,可以减少递归层数
题目链接:
Ac 代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define ll long long
const double eps=1e-3;
ll a[3000],l,r,ans;
bool vis[3000];
int cnt;
void pre(ll now)
{
if(now>r) return;
a[++cnt]=now;
pre(now*10+6),pre(now*10+8);
}
ll gcd(ll a,ll b)
{
return b==0?a:gcd(b,a%b);
}
void dfs(int now,int num,ll x)
{
if(now>cnt)
{
//printf("%d %d %lld\n",now,num,x);
if(num%2) ans+=(r/x-(l-1)/x);
else if(num) ans-=(r/x-(l-1)/x);
return;
}
ll tmp=x/gcd(x,a[now]);
dfs(now+1,num,x);
if((double)a[now]*tmp<=r+eps)
dfs(now+1,num+1,tmp*a[now]);
}
inline bool comp(ll x,ll y){return x>y;}
int main()
{
scanf("%lld%lld",&l,&r);
pre(6),pre(8);
std::sort(a+1,a+cnt+1,comp);
for(int i=cnt;i>=1;i--)
if(!vis[i])
for(int j=i-1;j>=1;j--)
if(!(a[j]%a[i]))
vis[j]=1;
int tmp=0;
for(int i=1;i<=cnt;i++)
if(!vis[i]) a[++tmp]=a[i];
cnt=tmp;
dfs(1,0,1);
printf("%lld\n",ans);
return 0;
}