Time Limit: 2 Sec Memory Limit: 64 MB
Submit: 1837 Solved: 673
[Submit][Status][Discuss]
【数据范围】
对于30%的数据,保证1 < =a < =b < =1000000
对于100%的数据,保证1 < =a < =b < =10000000000
容斥原理+搜索剪枝
方法同bzoj2393,但是这道题数据范围略大,所以DFS得时候要从后往前DFS,这样剪枝优化更明显。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
#define maxn 3005
using namespace std;
int cnt,tot;
ll l,r,ans,a[maxn],b[maxn];
bool tag[maxn];
void find(ll x)
{
if (x>r) return;
a[++cnt]=x;
find(x*10+6);find(x*10+8);
}
ll gcd(ll a,ll b)
{
return !b?a:gcd(b,a%b);
}
void dfs(int x,int flag,ll t)
{
if (!x)
{
if (t!=1) ans+=(r/t-(l-1)/t)*flag;
return;
}
dfs(x-1,flag,t);
ll tmp=gcd(t,a[x]);
if ((double)t*a[x]/tmp>(double)r) return;
dfs(x-1,-flag,t/tmp*a[x]);
}
int main()
{
scanf("%lld%lld",&l,&r);
find(6);find(8);
sort(a+1,a+cnt+1);
F(i,1,cnt) F(j,1,i-1) if (a[i]%a[j]==0){tag[i]=1;break;}
for(int i=1;a[i];i++) if (!tag[i]) b[++tot]=a[i];
cnt=tot;
F(i,1,cnt) a[i]=b[i];
dfs(cnt,-1,1);//要从大往小搜索,不然会TLE
printf("%lld\n",ans);
}