P2567
题解:先把幸运数全部筛出来,然后再把有些数是其他数的倍数的那些数再筛出来,接下来我们就可以容斥了,递归的时候从大的数先搞,因为这样我们对于一些超过R的数就可以尽快的跳出来,递归写法类似于背包问题的写法,每次我们对于当前的数可以有两种选择(取或 不取)
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn=3e3+10;
LL L,R;
LL a[maxn],b[maxn];
LL n,cnt;
LL vis[maxn];
void dfs1(LL u)
{
if(u>R){
return;
}
if(u>0){
a[++n]=u;
}
dfs1(u*10+6);
dfs1(u*10+8);
}
LL ans;
void dfs2(LL x,LL flag,LL t)
{
if(!x){
if(t!=1){
ans+=(R/t-(L-1)/t)*flag;
}
return;
}
dfs2(x-1,flag,t);
LL tmp=__gcd(t,a[x]);
if((double)t*a[x]/tmp>(double)R)return;//据网上说要开double防止溢出
dfs2(x-1,-flag,t/tmp*a[x]);
}
int main()
{
scanf("%lld%lld",&L,&R);
dfs1(0);
sort(a+1,a+1+n);
for(LL i=1;i<=n;i++){
for(LL j=1;j<i;j++){
if(a[i]%a[j]==0){
vis[i]=1;break;
}
}
}
for(LL i=1;i<=n;i++){
if(!vis[i]){
b[++cnt]=a[i];
}
}
for(LL i=1;i<=cnt;i++){
a[i]=b[i];
}
ans=0;
dfs2(cnt,-1,1);
printf("%lld\n",ans);
return 0;
}