51nod-1010 只包含因子2 3 5的数

题目传送门

方法一:

/*
	这种方法是通过暴力来解题。
*/
#include <iostream>
#include <stdio.h>
#include <algorithm>
#define MAXN 1000000
#define MAXM 1000000000000000100//注意:这里只填18个0不可以,还要加上100才能通过
//const long long MAXM = 1e18 + 100;
using namespace std;
long long num[MAXN];
int main(void)
{
	int count = 0;
	long long x = MAXM;

	for (long long i = 1; i < MAXM; i *= 2)
		for (long long j = 1; i*j < MAXM; j *= 3)
			for (long long k = 1; i*j*k < MAXM; k *= 5)
				num[count++] = i * j * k;
	//这里是把符合题意并且小于MAXM的数字全部存入数组之中
	sort(num, num + count);
	int T;

	scanf_s("%d", &T);
	while (T--)
	{
		long long n;//注意,这里必须是long long,如果是int不能通过

		scanf_s("%lld", &n);
		if (n == 1)//因为1在数组中能够找到,但是它并不是2 3 5的因数,它应该输出的是它的下一个数2
			printf("2\n");//因此我这里将它特殊化的拿出来等于2
		else
			printf("%lld\n", *lower_bound(num, num + count, n));//用二分搜索来节省时间
	}

	return 0;
}

方法二:

/*
	略有一些技巧
*/
#include <iostream>
#include <stdio.h>
#include <algorithm>
#define MAXN 11000//
using namespace std;
long long num[MAXN];
long long minnum(long long x, long long y, long long z)
{//用来求三个数的最大值
	long long temp = (x > y) ? y : x;
	return (temp > z) ? z : temp;
}
void ugly(void)
{
	long long A = 2, B = 3, C = 5;//这三个数表示的是当前倍数数字的最小值
	int idex2 = 0, idex3 = 0, idex5 = 0;//这三个数字表示用来乘过的次数
	num[0] = 1;//第一个数字为1,因为它乘什么就得什么

	for (int i = 1; i < MAXN; i++)
	{//计算前MAXN个元素,这个数组一直都在乘是增长得很快的
		long long m = minnum(A, B, C);
		num[i] = m;//把三个数字的最小值赋予num[i]以保证它的顺序

		if (A == m)//三个数的最小值是A
			A = 2 * num[++idex2];//那就在数列的下一个值来乘二,增大了A,并且保证了其最小
		if (B == m)
			B = 3 * num[++idex3];
		if (C == m)
			C = 5 * num[++idex5];
	}
}
int main(void)
{
	ugly();
	int T;

	scanf_s("%d", &T);
	while (T--)
	{
		long long n;

		scanf_s("%lld", &n);
		if (n == 1)
			printf("2\n");
		else
			printf("%lld\n", *lower_bound(num, num + MAXN, n));
	}

	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值