zznuoj2024天空在下着雨,证明我水 打表

问题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;
}

猜你喜欢

转载自blog.csdn.net/cloudy_happy/article/details/82053074
今日推荐