【样例输入1】 1 10 【样例输入2】 1234 4321
【样例输出1】 2 【样例输出2】 809
【数据范围】
对于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;
}