Bzoj2393 Cirno的完美算数教室
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\n",ans); 58 return 0; 59 } 60
本文为博主原创文章,转载请注明出处。