P2567 SCOI2010 幸运数字
P2567幸运数字
Description
计算
Solution
容斥。
我们要先找出幸运数字,才能检索近似幸运数字。这一部分直接跑一个搜索即可。
接下来考虑使用dfs求解。
搜索的意义很简单,就是在
对于每个
但搜索的复杂度奇高无比,故考虑剪枝。
剪枝的过程也十分好理解,即当
此时的代码依旧错误,原因是我们算重了很多(譬如
令
Code
#include <iostream>
#include <algorithm>
#include <cmath>
#define int long long
using namespace std;
const int N=1e6+9;
int a,b,ans;
int l[N],tot,luc[N],len;
bool mark[N];
void dfs(int sta){
if(sta>b)return;
if(sta)l[++tot]=sta;
bfs(sta*10+6);
bfs(sta*10+8);
}
bool cmp(int a,int b){return a>b;}
__int128 gcd(__int128 a,__int128 b){
if(!b)return a;
else return gcd(b,a%b);
}
__int128 lcm(__int128 a,__int128 b){
if(!a)return b;
return a/gcd(a,b)*b;
}
void dfs_(int t,int num,__int128 lsm){
if(lsm>b)return;
if(t>len){
if(!lsm)return;
int jud=(num%2)?1:-1;
ans+=jud*(floor(1.0*b/lsm)-ceil(1.0*a/lsm)+1);
return;
}
dfs_(t+1,num+1,lcm(lsm,luc[t]));
dfs_(t+1,num,lsm);
}
signed main(){
scanf("%lld%lld",&a,&b);
dfs(0);
for(int i=1;i<=tot;i++){
if(!mark[i])luc[++len]=l[i];
for(int j=i+1;j<=tot;j++)
if(!(l[j]%l[i]))mark[j]=true;
}//筛去已经是倍数的幸运数字
sort(luc+1,luc+1+len,cmp);
dfs_(1,0,0);
printf("%lld",ans);
return 0;
}