【数据范围】 对于30%的数据,保证1 < =a < =b < =1000000 对于100%的数据,保证1 < =a < =b < =10000000000
题意:
给出一个区间,让你求这个区间内的近似幸运数和幸运数有多少个
题解:
先把所有幸运数找出来,剔除后面容斥会导致重复的数字
然后进行容斥
一共进行2的n次方的选择
所以需要剪枝,剪枝注意数据会会超,所以用double
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; #define LL long long int m,n; LL l,r,a[3000],b[3000],ans; bool vis[3000]; void init(LL x) { if(x>r) return; if(x) a[m++]=x; init(x*10+6); init(x*10+8); } LL gcd(LL a,LL b){return b==0?a:gcd(b,a%b);} void dfs(int now,int cnt,LL x) { if(now>=n){ if(!cnt) return ; if(cnt&1) ans+=r/x-(l-1)/x; else ans-=r/x-(l-1)/x; return; } dfs(now+1,cnt,x); LL tmp=x/gcd(a[now],x); if((double)a[now]*tmp<=r) dfs(now+1,cnt+1,tmp*a[now]); } int main() { // freopen("in.txt","r",stdin); while(scanf("%lld%lld",&l,&r)!=EOF) { m=n=0; init(0); sort(a,a+m); memset(vis,0,sizeof(vis)); for(int i=0;i<m;i++){ if(!vis[i]){ b[n++]=a[i]; for(int j=i+1;j<m;j++) if(a[j]%a[i]==0) vis[j]=1; } } for(int i=0;i<n;i++) a[i]=b[n-i-1]; ans=0; dfs(0,0,1); printf("%lld\n",ans); } return 0; }
