[bzoj2393][bzoj1853]Cirno的完美算数教室&&幸运数字【暴力】【容斥】
[题目描述]
Submit: 703 Solved: 418
[Submit][Status][Discuss]
Description
~Cirno发现了一种baka数,这种数呢~只含有2和⑨两种数字~~
现在Cirno想知道~一个区间中~~有多少个数能被baka数整除~
但是Cirno这么天才的妖精才不屑去数啦
只能依靠聪明的你咯。
Input
一行正整数L R
( 1 < L < R < 10^10)
Output
一个正整数,代表所求的答案
Sample Input
1 100
Sample Output
58
[题解]暴力容斥一发,T飞。。。
加了两个剪枝跑得飞快 1.在容斥时若i是j的倍数,则i是无效的。直接跳过
2.dfs时从大的往小的做,可以尽早跳出许多非法状态。
/* -------------- user Vanisher problem bzoj-2393 ----------------*/ # include <bits/stdc++.h> # define ll long long # define N 10010 using namespace std; ll num,p[N],ans,r,l,f[N]; ll read(){ ll tmp=0, fh=1; char ch=getchar(); while (ch<'0'||ch>'9'){if (ch=='-') fh=-1; ch=getchar();} while (ch>='0'&&ch<='9'){tmp=tmp*10+ch-'0'; ch=getchar();} return tmp*fh; } ll gcd(ll x, ll y){ if (x%y==0) return y; else return gcd(y,x%y); } bool cmp(ll x, ll y){ return x>y;} void solve(ll k, ll tag, ll sum){ if (k>num){ if (tag==0) return; if (tag%2==1) ans=ans+r/sum-(l-1)/sum; else ans=ans-r/sum+(l-1)/sum; return; } solve(k+1,tag,sum); ll t=gcd(sum,p[k]); if (r/(sum/t)>=p[k]) solve(k+1,tag+1,sum/t*p[k]); } int main(){ l=read(); r=read(); p[0]=0; ll pl=0, pr=0; while (pl<=pr){ ll x=p[pl++]; if (x*10+2<=r) p[++pr]=x*10+2; if (x*10+9<=r) p[++pr]=x*10+9; } num=pr; for (int i=1; i<=num; i++){ f[i]=true; for (int j=1; j<i; j++) if (p[i]%p[j]==0) {f[i]=false; break;} } int k=0; for (int i=1; i<=num; i++) if (f[i]==true) p[++k]=p[i]; num=k; sort(p+1,p+num+1,cmp); solve(1,0,1); cout<<ans<<endl; return 0; }