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 #define db double 3 #define ll long long 4 #define cl(x) scanf("%lld",&x) 5 #define pl(x) printf("%lld\n",x) 6 const int N = 1e5 + 5; 7 const int mod = 1e9 + 7; 8 using namespace std; 9 ll a[N],b[N];10 bool v[N];11 int m=0,n=0;12 ll l,r,ans=0;13 ll gcd(ll x,ll y){14 return y==0?x:gcd(y,x%y);15 }16 void init(ll x){17 if(x>r) return ;18 else if(x>0) a[++m]=x;//0不加入19 init(x*10+6);20 init(x*10+8);21 }22 void dfs(int x,int y,ll z)//表示:前x个数字中选y个数字时的lcm为z23 {24 if(x==n){25 if(y&1) ans+=r/z-(l-1)/z;//奇数加26 if(y%2==0&&y!=0) ans-=r/z-(l-1)/z;//偶数减27 return;28 }29 dfs(x+1,y,z);30 ll s=z/gcd(a[x+1],z);31 if((db(s)*a[x+1])<=r) dfs(x+1,y+1,a[x+1]*s);//一个剪枝:lcm<=r32 }33 int main()34 {35 cl(l),cl(r);36 init(0);37 sort(a+1,a+m+1);38 for(int i=1;i<=m;i++){ //去掉内部倍数情况39 if(!v[i]){40 b[++n]=a[i];41 for(int j=i+1;j<=m;j++)42 if(a[j]%a[i]==0) v[j]=1;43 }44 }45 for(int i=1;i<=n;i++) a[n+1-i]=b[i];//数字从大到小排46 dfs(0,0,1);47 pl(ans);48 return 0;49 }