https://www.luogu.com.cn/problem/U136049
我只是大自然的搬运工,这题目是蓝桥杯的一道真题。我出了几个测试数据,就把它放到了洛谷的个人题库。
到x星球旅行的游客都被发给一个整数,作为游客编号。x星的国王有个怪癖,他只喜欢数字3,5和7。 国王规定,游客的编号如果只含有因子:3,5,7,就可以获得一份奖品。
我们来看前10个幸运数字是: 3 5 7 9 15 21 25 27 35 45。 因而第11个幸运数字是:49
小明领到了一个幸运数字 x,他去领奖的时候,人家要求他准确地说出这是第几个幸运数字,否则领不到奖品。
小明领取到的幸运数字 x。 1 <= x < 10^14。
一个正整数,表示这是第几个幸运数字
输入 #1复制
49输出 #1复制
111 <= x < 10^14
维护一个计数变量,暴力枚举从3到x,每个数都判断是否是幸运数,如果是幸运数,计数变量+1。
难点在于如何判断一个数是否是幸运数。由于一个幸运数的因子只有3,5,7。因此只需要让它不断除以3直到不能整除3为止,然后不断除以5直到不能整除5为止,然后不断除以7直到不能整除7为止。最后的结果如果是1,则原数就是幸运数。
但是对于x最大可达10^14,显然对于这样的数据规模,这种算法会超时。
#include<iostream> #include<cstdio> #include<vector> #include<algorithm> using namespace std; typedef long long ll; int main() { ll x; scanf("%lld", &x); int ans=0; for(ll i=3; i<=x; i++) { ll t=i; while(t%3==0) t /= 3; while(t%5==0) t /= 5; while(t%7==0) t /= 7; if(t==1) { ans++; if(i==x) break; } } printf("%d", ans); return 0; }来自于某猛女 Orz。。。,那么可以通过三重循环枚举阶数,统计 的种数。 但是需要注意两个问题
1、pow(3,a)*pow(5,b)*pow(7,c) 可能会超出long long返回,所以不要用 long long 去接收。要用 double类型接收,而 pow() 的返回值本身就是 double
2、为什么 if 里面的条件是 < 而不是 <= ?因为这么枚举多算了 x=1(事实上这是不合法的),所以不取等号(不算上等于x的情况)刚好就抵掉了
#include<stdio.h> #include<math.h> int main(void) { long int n,m; scanf("%ld",&n); int a,b,c,count=0; for(a=0 ; pow(3,a)<n ; a++ ) { for(b=0 ; pow(5,b)<n ; b++) { for(c=0 ; pow(7,c)<n ; c++) { if(pow(3,a)*pow(5,b)*pow(7,c)<n) { count++; } } } } printf("%d",count); return 0; }假设已经知道前 i–1 个幸运数,如何推出第 i 个幸运数? 显然第 i 个数可以由前 i-1 个数推出来。第 i 个数有可能是前 i-1 个数中的某个数乘以3得到,也可能是前 i-1 个数中的某个数乘以5得到,也可能是前 i-1 个数中的某个数乘以7得到。不太好表述,直接看代码,也比较好懂。
#include<iostream> #include<cstdio> #include<vector> #include<algorithm> using namespace std; typedef long long ll; vector<ll> num; // 求 num[ num.size() ] 的待定值 // 返回一个大于 num[ num.size()-1 ] 的待定值 // 可用二分法优化,但没必要 ll getNum(int key) { for(int i=0; i<num.size(); i++) { ll t = num[i]*key; if(t > num[ num.size()-1 ]) return t; } } int main() { num.push_back(3); num.push_back(5); num.push_back(7); ll x; scanf("%lld", &x); while(num[ num.size()-1 ] < x) { ll a = getNum(3); ll b = getNum(5); ll c = getNum(7); ll t = min(a, min(b, c)); num.push_back(t); } printf("%d", num.size()); return 0; }显然,对于解法3的 getNum() 可以换成 二分法 来优化! 对比一下耗时,变化不大,因为 对于测试数据中最大的 x, 不定长数组 num 的元素个数也只是差不多2000而已,所以对于这个优化,效果不是很明显。
#include<iostream> #include<cstdio> #include<vector> #include<algorithm> using namespace std; typedef long long ll; vector<ll> num; // 二分法 ll getNum(int key) { int l=0, r=num.size()-1; while(l<r) { int m=(l+r)/2; if (num[m]*key <= num[ num.size()-1 ]) l=m+1; else r=m; } return num[r]*key; } int main() { num.push_back(3); num.push_back(5); num.push_back(7); ll x; scanf("%lld", &x); while(num[ num.size()-1 ] < x) { ll a = getNum(3); ll b = getNum(5); ll c = getNum(7); ll t = min(a, min(b, c)); num.push_back(t); } printf("%d", num.size()); return 0; }
