Bzoj2393 Cirno的完美算数教室

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 468  Solved: 284

Description

~Cirno发现了一种baka数,这种数呢~只含有2和⑨两种数字~~
现在Cirno想知道~一个区间中~~有多少个数能被baka数整除~
但是Cirno这么天才的妖精才不屑去数啦
只能依靠聪明的你咯。
 
 

Input

一行正整数L R
( 1 < L < R < 10^10)
 

Output

一个正整数,代表所求的答案
 

Sample Input

1 100

Sample Output

58

HINT

数学 DFS 容斥原理

边听《⑨的完美算术教室》边做这题,果然整个人都baka了

只含⑨和2的数字没多少个,暴搜出来再去掉是其他baka数倍数的,剩下大概30+

然后利用容斥原理DFS,加上是一个baka数的倍数的,减去是两个baka数的倍数的……

计算方法当然是R/lcm,当lcm大到一定程度就可以直接剪枝,所以还算快

 1 /*by SilverN*/
 2 #include<algorithm>
 3 #include<iostream>
 4 #include<cstring>
 5 #include<cstdio>
 6 #include<cmath>
 7 #include<vector>
 8 #define LL long long
 9 using namespace std;
10 const int mxn=5010;
11 int read(){
12     int x=0,f=1;char ch=getchar();
13     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
14     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
15     return x*f;
16 }
17 LL a[mxn];int cnt=0;
18 LL L,R;
19 int n;
20 void GT(LL x){
21     if(x>R)return;
22     a[cnt++]=x;
23     GT(x*10+2);GT(x*10+9);
24     return;
25 }
26 LL ans,lim;
27 bool del[mxn];
28 LL gcd(LL a,LL b){
29     if(!b)return a;return gcd(b,a%b);
30 }
31 void DFS(int pos,int rc,LL lcm){
32     if(pos>n){
33         if(lcm!=1)ans+=lim/lcm*rc;
34         return;
35     }
36     int i,j;
37     DFS(pos+1,rc,lcm);//不选 
38     LL tmp=lcm/gcd(lcm,a[pos])*a[pos];
39     if(tmp>lim)return;
40     DFS(pos+1,-rc,tmp);
41     return;
42 }
43 int main(){
44     int i,j;
45     L=read();R=read();
46     GT(0);cnt--;
47     sort(a+1,a+cnt+1);
48     for(i=1;i<=cnt;i++)
49         for(j=1;j<i;j++){
50             if(a[i]%a[j]==0)del[i]=1;
51         }
52     for(i=1;i<=cnt;i++)if(!del[i])a[++n]=a[i];
53     lim=R;
54     DFS(1,-1,1);
55     lim=L-1;
56     DFS(1,1,1);
57     printf("%lld
",ans);
58     return 0;
59 }
60 
原文地址:https://www.cnblogs.com/SilverNebula/p/6575489.html