数学太差自闭了。
题意:
给一个数n,问你大于等于n的数中,可以拆分成3的幂之和的最小的数,其中每个幂最多出现一次
题解:
先将n分解成三进制,然后观察,当某位出现2的时候,我们需要从大于这位的幂开始寻找一位出现0次的幂,将其改成1,同时将小于这个幂出现次数被改成1的幂的出现次数全部改成0
如: ,3^0这个幂出现次数为2,那么从该幂开始寻找一个幂出现次数为0,那么就是3^3将其换成1,同时3^0,3^1,3^2出现次数全部换成0,即答案为
证明:
考虑极端情况:
那么对于任意的三位三进制数,如果每一位都不小于1,同时如果某位为2,那么不可能大于等于
因此得证.
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n, q, g;
int three[70];
void trans(){
memset(three, 0, sizeof three);
g = 0;
ll t = n;
while(t){
three[++g] = t % 3;
t /= 3;
}
}
ll process(){
trans();
ll now = 0;
for(int i = 1; i <= g; i++){
if(three[i] == 2){
for(int j = i + 1; ; j++)
if(three[j] == 0){
if(now < j) now = j;
break;
}
}
}
g = max(g, now);
if(!now) return n;
else {
for(int i = 1; i < now; i++)
three[i] = 0;
three[now] = 1;
ll ans = 0;
for(int i = g; i >= 1; i--)
ans = (ans * 3 + three[i]);
return ans;
}
}
int main()
{
scanf("%I64d", &q);
while(q--){
scanf("%I64d", &n);
ll ans = process();
printf("%I64d\n", ans);
}
return 0;
}