问题2024--天空在下着雨,证明我水
2024: 天空在下着雨,证明我水
时间限制: 1 Sec 内存限制: 128 MB
提交: 296 解决: 57
[提交] [状态] [讨论版] [命题人:admin]
题目描述
由算数基本定理可知:任何一个大于1的自然数 K,如果K不为质数,那么K可以唯一分解成有限个质数的乘积。
若一个大于1的自然数,将其分解为质数乘积的形式后,分解所得的质数只包含(2,3,5),那么我们称n为完美数。
那么,前10个完美数是:2,3,4,5,6,8,9,10,12,15。
现在给出一个数n,求大于等于n的最小完美数。
输入
第1行:一个数T,表示后面用作输入测试的数的数量。(1 <= T <= 10000)
第2 - T + 1行:每行1个数N(1 <= N <= 10^18)
输出
共T行,每行1个数,输出大于等于n的最小完美数。
样例输入
1 1
样例输出
2
思路:
刚开始以为打表不可行,结果发现n越大,完美数的间隔越大,其实打表后就会发现其实才15000多个,这里要强调一下STL二分
函数的注意点,lower_bound(l,r,n)函数查找的是区间[ l ,r )里的最先出现大于等于n的地址,而upper_bound(l , r , n)函数查找到的结果则是区间[ l , r )里 大于 n 的最先出现的地址 ,并且被查找的序列是一个非严格单调递增的序列 ,是故这道题使用lower_bound()函数自然是最明智的选择;
代码:
#include<cstdio>
#include<algorithm>
#include<set>
#define ll long long
using namespace std;
const int maxn = (int)1e6;
const ll MAXN = (ll)1e18 + 10050;
ll p[maxn];
int pos;
void init()
{
pos = 0;
for (ll i = 1;i <= MAXN;i *= 2)
for (ll j = 1;j * i <= MAXN;j *= 3)
for (ll k = 1;k * i * j <= MAXN;k *= 5)
p[pos ++] = i * j * k;
sort(p,p + pos);
}
int main()
{
int t;
ll n;
init();
scanf("%d",&t);
while (t --)
{
scanf("%lld",&n);
printf("%lld\n",*lower_bound(p + 1,p + pos + 1,n));
}
return 0;
}