[luogu2576 SCOI2010] 幸運數字 (容斥原理)
阿新 • • 發佈:2018-07-27
www. 傳送門 long long org += 容斥 但是 scrip include
傳送門
Description
在中國,很多人都把6和8視為是幸運數字!lxhgww也這樣認為,於是他定義自己的“幸運號碼”是十進制表示中只包含數字6和8的那些號碼,比如68,666,888都是“幸運號碼”!但是這種“幸運號碼”總是太少了,比如在[1,100]的區間內就只有6個(6,8,66,68,86,88),於是他又定義了一種“近似幸運號碼”。lxhgww規定,凡是“幸運號碼”的倍數都是“近似幸運號碼”,當然,任何的“幸運號碼”也都是“近似幸運號碼”,比如12,16,666都是“近似幸運號碼”。
現在lxhgww想知道在一段閉區間[a, b]內,“近似幸運號碼”的個數。
Input
輸入數據是一行,包括2個數字a和b
Output
輸出數據是一行,包括1個數字,表示在閉區間[a, b]內“近似幸運號碼”的個數
Sample Input
1 10
Sample Output
2
HINT
對於30%的數據,保證1<=a<=b<=1000000
對於100%的數據,保證1<=a<=b<=10000000000
Solution
預處理幸運號碼(極少),去掉其中互為倍數的
dfs枚舉其中的數,求lcm用邊界除一下就得到倍數個數
考慮容斥,算完即可
Code
//By Menteur_Hxy #include<cstdio> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> #define F(i,a,b) for(register int i=(a);i<=(b);i++) using namespace std; typedef long long LL; const int N=3010; bool vis[N]; int n,m; LL l,r,ans; LL a[N],b[N]; void pre(LL x) { if(x>r) return ; if(x) a[++n]=x; pre(x*10+6);pre(x*10+8); } LL gcd(LL a,LL b) {return !b?a:gcd(b,a%b);} void dfs(int x,int y,LL z) { if(x>m) { if(y&1) ans+=r/z-(l-1)/z; else if(y) ans-=r/z-(l-1)/z; return ; } dfs(x+1,y,z); LL tmp=z/gcd(a[x],z); if((double)a[x]<=(double)r/tmp) //防爆類型 dfs(x+1,y+1,a[x]*tmp); } int main() { scanf("%lld%lld",&l,&r); pre(0); sort(a+1,a+1+n); F(i,1,n) if(!vis[i]) { b[++m]=a[i]; F(j,i+1,n) if(a[j]%a[i]==0) vis[j]=1; } F(i,1,m) a[i]=b[m-i+1]; dfs(1,0,1); printf("%lld",ans); return 0; }
[luogu2576 SCOI2010] 幸運數字 (容斥原理)