1. 程式人生 > >P2567 [SCOI2010]幸運數字 DFS+容斥定理

P2567 [SCOI2010]幸運數字 DFS+容斥定理

spa mes names align pri efi 很多 個數 十進制

P2567 [SCOI2010]幸運數字

題目描述

在中國,很多人都把6和8視為是幸運數字!lxhgww也這樣認為,於是他定義自己的“幸運號碼”是十進制表示中只包含數字6和8的那些號碼,比如68,666,888都是“幸運號碼”!但是這種“幸運號碼”總是太少了,比如在[1,100]的區間內就只有6個(6,8,66,68,86,88),於是他又定義了一種“近似幸運號碼”。lxhgww規定,凡是“幸運號碼”的倍數都是“近似幸運號碼”,當然,任何的“幸運號碼”也都是“近似幸運號碼”,比如12,16,666都是“近似幸運號碼”。

現在lxhgww想知道在一段閉區間[a, b]內,“近似幸運號碼”的個數。

輸入輸出格式

輸入格式:

輸入數據是一行,包括2個數字a和b

輸出格式:

輸出數據是一行,包括1個數字,表示在閉區間[a, b]內“近似幸運號碼”的個數

輸入輸出樣例

輸入樣例
1 10
輸出樣例
2

說明

對於100%的數據,保證1<=a<=b<=10000000000

思路:

代碼:

 1 //#include"bits/stdc++.h"
 2 #include <sstream>
 3 #include <iomanip>
 4 #include"cstdio"
 5 #include"map"
 6 #include"set"
 7 #include"cmath
" 8 #include"queue" 9 #include"vector" 10 #include"string" 11 #include"cstring" 12 #include"time.h" 13 #include"iostream" 14 #include"stdlib.h" 15 #include"algorithm" 16 #define db double 17 #define ll long long 18 #define vec vector<ll> 19 #define mt vector<vec> 20 #define ci(x) scanf("%d",&x) 21
#define cd(x) scanf("%lf",&x) 22 #define cl(x) scanf("%lld",&x) 23 #define pi(x) printf("%d\n",x) 24 #define pd(x) printf("%f\n",x) 25 #define pl(x) printf("%lld\n",x) 26 //#define rep(i, x, y) for(int i=x;i<=y;i++) 27 #define rep(i,n) for(int i=0;i<n;i++) 28 const int N = 1e5 + 5; 29 const int mod = 1e9 + 7; 30 const int MOD = mod - 1; 31 const int inf = 0x3f3f3f3f; 32 const db PI = acos(-1.0); 33 const db eps = 1e-10; 34 using namespace std; 35 ll a[N],b[N]; 36 bool v[N]; 37 int m=0,n=0; 38 ll l,r,ans=0; 39 ll gcd(ll x,ll y){ 40 return y==0?x:gcd(y,x%y); 41 } 42 void init(ll x){ 43 if(x>r) return ; 44 else if(x>0) a[++m]=x;//0不加入 45 init(x*10+6); 46 init(x*10+8); 47 } 48 void dfs(int x,int y,ll z)//表示:前x個數字中選y個數字時的lcm為z 49 { 50 if(x==n){ 51 if(y&1) ans+=r/z-(l-1)/z;//奇數加 52 if(y%2==0&&y!=0) ans-=r/z-(l-1)/z;//偶數減 53 return; 54 } 55 dfs(x+1,y,z); 56 ll s=z/gcd(a[x+1],z); 57 if((db(s)*a[x+1])<=r) dfs(x+1,y+1,a[x+1]*s);//一個剪枝:lcm<=r 58 } 59 int main() 60 { 61 cl(l),cl(r); 62 init(0); 63 sort(a+1,a+m+1); 64 for(int i=1;i<=m;i++){//去掉內部倍數情況 65 if(!v[i]){ 66 b[++n]=a[i]; 67 for(int j=i+1;j<=m;j++) 68 if(a[j]%a[i]==0) v[j]=1; 69 } 70 } 71 for(int i=1;i<=n;i++) a[n+1-i]=b[i];//數字從大到小排 72 dfs(0,0,1); 73 pl(ans); 74 return 0; 75 }

P2567 [SCOI2010]幸運數字 DFS+容斥定理