BZOJ2393 Cirno的完美算数教室
Description
~Cirno发现了一种baka数,这种数呢~只含有2和⑨两种数字~~
现在Cirno想知道~一个区间中~~有多少个数能被baka数整除~
但是Cirno这么天才的妖精才不屑去数啦
只能依靠聪明的你咯。
Input
一行正整数L R
( 1 < L < R < 10^10)
Output
一个正整数,代表所求的答案
Sample Input
1 100
Sample Output
58
题解:搜索+容斥原理
求一个区间内的某些数倍数的个数。
预处理所有的baka数,有2000多个,然后把某些baka数的倍数去掉后有400多个baka数,然后
加一个剪枝,当lcm>r时不搜索,能过。
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define LL long long using namespace std; LL l,r,p,q,ans,a[1020],b[1020],vis[1020]; void get_baka(LL x){//这里没开LL,卡了一个小时。我是不是没救了QAQ if(x>r)return; if(x)a[++p]=x; get_baka(x*10+2);get_baka(x*10+9); } LL gcd(LL i,LL j){ return j==0?i:gcd(j,i%j); } void dfs(int now,int cnt,LL lcm){ if(now==q+1){ if(cnt&1)ans=ans+r/lcm-(l-1)/lcm; else if(cnt)ans=ans-r/lcm+(l-1)/lcm; return; } dfs(now+1,cnt,lcm); LL vv=(b[now]*lcm)/gcd(lcm,b[now]); if(vv<=r)dfs(now+1,cnt+1,vv); } int main(){ scanf("%lld%lld",&l,&r); get_baka(0); sort(a+1,a+p+1); for(int i=1;i<=p;i++){ if(!vis[i]){ b[++q]=a[i]; for(int j=i+1;j<=p;j++) if(a[j]%a[i]==0)vis[j]=true; } } dfs(1,0,1); cout<<ans<<endl; return 0; }