K的因子中只包含2 3 5。满足条件的前10个数是:2,3,4,5,6,8,9,10,12,15。
所有这样的K组成了一个序列S,现在给出一个数n,求S中 >= 给定数的最小的数。
例如:n = 13,S中 >= 13的最小的数是15,所以输出15。
Input
第1行:一个数T,表示后面用作输入测试的数的数量。(1 <= T <= 10000)
第2 - T + 1行:每行1个数N(1 <= N <= 10^18)
Output
共T行,每行1个数,输出>= n的最小的只包含因子2 3 5的数。
Sample Input
5
1
8
13
35
77
Sample Output
2
8
15
36
80
先对范围内的这种数打表,然后二分查找位置,可以自己手写二分,也可以直接用lower_bound,十分方便。
函数lower_bound()在first和last中的前闭后开区间进行二分查找,返回大于或等于val的第一个元素位置。如果所有元素都小于val,则返回last的位置。
举例如下:
一个数组number序列为:4,10,11,30,69,70,96,100。设要插入数字3,9,111,pos为要插入的位置的下标,
则:
pos = lower_bound( number, number + 8, 3) - number,pos = 0.即number数组的下标为0的位置。
pos = lower_bound( number, number + 8, 9) - number, pos = 1,即number数组的下标为1的位置(即10所在的位置)。
pos = lower_bound( number, number + 8, 111) - number, pos = 8,即number数组的下标为8的位置(但下标上限为7,所以返回最后一个元素的下一个元素)。
所以,要记住:函数lower_bound()在first和last中的前闭后开区间进行二分查找,返回大于或等于val的第一个元素位置。如果所有元素都小于val,则返回last的位置,且last的位置是越界的!!
二分代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll MAXN = 1e18+1000;
ll a[110000];
int cnt;
void init(){
cnt=0;
for(ll i=1;i<MAXN;i*=2){
for(ll j=1;i*j<MAXN;j*=3){
for(ll k=1;i*j*k<MAXN;k*=5){
a[cnt++]=i*j*k;
}
}
}
sort(a,a+cnt);
}
int main(){
int T;
init();
cin>>T;
while(T--){
ll n,ans;
scanf("%lld",&n);
if(n<=2) ans=2;
else{
ll l=0,r=cnt-1;
ll mid;
while(l<r){
mid=(l+r)>>1;
if(a[mid]>=n) r=mid;
else l=mid+1;
}
ans=a[r];
}
printf("%lld\n",ans);
}
return 0;
}
lower_bound 做法:
#include <bits/stdc++.h>
#include <algorithm>
using namespace std;
typedef long long ll;
const ll MAXN = 1e18+1000;
ll a[110000];
int cnt;
void init(){
cnt=0;
for(ll i=1;i<MAXN;i*=2){
for(ll j=1;i*j<MAXN;j*=3){
for(ll k=1;i*j*k<MAXN;k*=5){
a[cnt++]=i*j*k;
}
}
}
sort(a,a+cnt);
}
int main(){
init();
int t;
cin>>t;
while(t--){
ll n;
scanf("%lld",&n);
ll ans=lower_bound(a,a+cnt,n)-a;
if(ans==0) ans++;
printf("%lld\n",a[ans]);
}
return 0;
}