周赛十四 A好数

51Nod 1010

问题描述: 假如整数n除以m,结果是无余数的整数,那么我们称 m 就是 n 的因子。 假如一个数, 他的因子只包含 2、3、5,我们则称这个数是一个好数。 小A 想知道大于或等于 n 的最小的好数是多少?
输入描述:
第1行:一个数 t,表示后面用作输入测试的数的数量。
第 2 ~ t+1行:每行1个数 n. 1<=n<=1e18.
输出描述:
共 t 行,每个样例输出 1 个数,输出大于等于 n 的最小的只包含因子 2、3、 5的数.

示例:
输入 #1:

4
1
13
17
22

输出 #1:

2
15
18
24

基本思路:找出所有小于1e18并且只由2,3,5相乘的数,存入数组,排序再二分查找.
下面有两种做法:
1
找出所有由2相乘的数,如2,4,8…存入一个数组.
3和5也一样.
枚举2 ^a + 3 ^b + 5 ^c<1e18.

#include <algorithm>
#include <cstdio>
using namespace std;
typedef long long ll;
const int N = 5e5;
const int M = 100;
const ll inf = 1e18;
long long a[N], a2[M], a3[M], a5[M];
int cnt = 0;
void f() {
	//分块存入数组这部分,其实可以用pow()解决
    a2[0] = a3[0] = a5[0] = 1;
    int c2, c3, c5;
    for (int i = 1; i <= 60; i++) {
        a2[i] = a2[i - 1] * 2;
        if (a2[i] > inf) {
            c2 = i;
            break;
        }
    }
    for (int i = 1; i <= 40; i++) {
        a3[i] = a3[i - 1] * 3;
        if (a3[i] > inf) {
            c3 = i;
            break;
        }
    }
    for (int i = 1; i <= 30; i++) {
        a5[i] = a5[i - 1] * 5;
        if (a5[i] > inf) {
            c5 = i;
            break;
        }
    }
    for (int i = 0; i < c2; i++) {
        for (int j = 0; j < c3; j++) {
            for (int k = 0; k < c5; k++) {
            	//注意这里,连乘的话会爆long long
            	//因为弹出当前循环,j还是增加,i和j的部分就可能爆了
                if (a2[i] > (inf / (a3[j] * a5[k]))) {
                    break;
                }
                a[cnt++] = a2[i] * a3[j] * a5[k];
            }
        }
    }
}
int main() {
    ll t, n, x;
    f();
    scanf("%lld", &t);
    sort(a, a + cnt);
    while (t--) {
        scanf("%lld", &n);
        //第一项是1,不要
        x = lower_bound(a + 1, a + cnt, n) - a;
        printf("%lld\n", a[x]);
    }
    return 0;
}

2
dfs搜索,三个分岔,乘以2,3,5.
通过代码1 ,知道大概有1e5个数.

#include<cstdio>
#include<algorithm>
#include<map>
using namespace std;
typedef long long ll;
const int N = 2e5;
const ll inf = 1e18;
map<ll, int> mp;
ll a[N];
int cnt = 0;
void dfs(ll sum,ll x){
    sum *= x;
    //剪枝,有的数据就不用再搜索了
    //不然搜索次数超过int范围了
    if(sum>inf||mp[sum]){
        return;
    }
    a[cnt++] = sum;
    mp[sum]++;
    dfs(sum, 2);
    dfs(sum, 3);
    dfs(sum, 5);
}
int main(){
    ll t, n;
    dfs(1, 1);
    scanf("%lld", &t);
    sort(a, a + cnt);
    while(t--){
        scanf("%lld", &n);
        int x = lower_bound(a+1, a + cnt, n) - a;
        printf("%lld\n", a[x]);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值