【Luogu】P2567幸运数字(容斥爆搜)
先预处理出幸运数,把成倍数关系的剔掉,然后用容斥原理搜索一下。
这里的容斥很像小学学的那个“班上有n个同学,有a个同学喜欢数学,b个同学喜欢语文……”那样。
#include<cstdio> #include<cstdlib> #include<cctype> #include<algorithm> #include<cstring> #define maxn 200020 using namespace std; inline long long read(){ long long num=0,f=1; char ch=getchar(); while(!isdigit(ch)){ if(ch=='-') f=-1; ch=getchar(); } while(isdigit(ch)){ num=num*10+ch-'0'; ch=getchar(); } return num*f; } long long q[maxn];int tot; long long d[maxn];int cnt; bool vis[maxn]; void find(int deep,long long now){ if(deep==0){ q[++tot]=now; return; } find(deep-1,now*10+6); find(deep-1,now*10+8); } bool cmp(long long a,long long b){ return a>b; } long long calc(long long l,long long r,long long e){ if(l%e==0) l/=e; else l=l/e+1; r/=e; return r-l+1; } long long gcd(long long a,long long b){ return b==0?a:gcd(b,a%b); } long long ans=0; long long a,b; void dfs(int deep,int Cnt,long long val){ if(val>b) return; if(deep>cnt){ if(Cnt==0) return; ans+=calc(a,b,val)*(Cnt&1?1:-1); return; } dfs(deep+1,Cnt,val); long long tmp=val/gcd(val,d[deep]); if(1.0*tmp*d[deep]<=b) dfs(deep+1,Cnt+1,tmp*d[deep]); } int main(){ a=read(),b=read(); for(int i=1;i<=10;++i) find(i,0); for(int i=1;i<=tot;++i){ if(vis[i]==0) d[++cnt]=q[i]; for(int j=i+1;j<=tot;++j) if(q[j]%q[i]==0) vis[j]=1; } sort(d+1,d+cnt+1,cmp); dfs(1,0,1); printf("%lld\n",ans); return 0; }