做网站建设的公司/网站广告策划
题目链接: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;
}
风可以吹走疲惫,带走忧伤