题目链接:https://vjudge.net/contest/338207#problem/E
翻译:
给定一个数n,求大于或等于n的最小数
这个数满足:3的不同幂次相加。
分析:
将n用三进制表示出来,分析可得只有0和1时,这样的数才符合题意。
可以从高位开始遍历(保持它最小),找到第一个3进制位为2的(如果没有则表示这个数本身就是符合要求的数)。拿14来说它的3进制数是112,从高位到低位第三位为2,记录2所在的位置,从该标记位到高位遍历,为2则向高位进1,最后变为1000
代码:
#include<cstdio>
#include<cstring>
typedef long long LL;
int a[200],k;
void init()
{
memset(a,0,sizeof(a));
k=0;
}
void solve(LL m)
{
while(m)
{
a[k++]=m%3;
m/=3;
}
}
LL quick(LL x,LL nn)/*pow函数是求浮点数的,会造成精度损失,最好是用快速幂*/
{
LL res=1;
while(nn)
{
if(nn&1)
res=res*x;
x=x*x;
nn>>=1;
}
return res;
}
int main()
{
int T;
LL n;
scanf("%d",&T);
while(T--)
{
init();
scanf("%lld",&n);
solve(n);
int lab,flag=0;
for(int i=k-1; i>=0; i--)
{
if(a[i]==2)
{
lab=i;/*从高位到低位找到第一个2的位置*/
flag=1;
break;
}
}
if(!flag)
printf("%lld\n",n);
else
{
LL sum=0;
for(int i=lab; i<k; i++)
{
if(a[i]==2)
{
a[i]=0;
a[i+1]++;
}
}
if(a[k])
k++;
for(int i=k-1; i>=lab; i--)
{
sum+=a[i]*quick(3,i);
}
printf("%lld\n",sum);
}
}
return 0;
}
对于n为int范围内,也可以用递归求解
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
LL n;
int f(int x)
{
if(x==0)
return 1;
if(x%3>1)
return 0;
return f(x/3);
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%lld",&n);
while(!f(n))
n++;
printf("%lld\n",n);
}
return 0;
}
风可以吹走疲惫,带走忧伤