题意:给你一个正整数n。你真的很喜欢好的数字,所以你想找到最小的好数字大于或等于n。 如果正整数可以表示为3的不同幂的和(即不允许3的幂的重复),则称为好整数。
题解:这题跟dp中的二进制优化思路差不多,就是凑数,预先用数组存好3的各次幂,然后先倒着用大的凑,如果恰好凑成那皆大欢喜,如果没有凑成,那就从小的开始‘回溯’,把已经加过的小减去,把遇到的第一个没有用的(说明在凑数的过程中减去这个数会小于零,具体见代码)加上去,那得到的数一定是比n大的最小的满足题意的数。
AC代码:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
ll s[40];
int vis[40];
ll po(int x,int y){
ll sum=1;
while(y--){
sum*=x;
}
return sum;
}
int main(){
for(int i=0;i<=38;i++)s[i]=po(3,i);//初始化
int t;
cin>>t;
while(t--){
memset(vis,0,sizeof(vis));
ll n;
cin>>n;
ll sum=0,p=n;
for(int i=38;i>=0;i--){//从大的开始减,先把能减的减掉
if(p>=s[i]){
vis[i]=1;
p-=s[i];
sum+=s[i];
}
}
if(p==0)cout<<sum<<endl;//正好可以凑成,直接输出
else{//下面这个找大于n的最小的sum相当于回溯
for(int i=0;i<=38;i++){
if(!vis[i]){//遇到的第一个没有使用过的值(即p<s[i]),加上这个一定会使sum大于n;
sum+=s[i];
break;
}
else sum-=s[i];//保证sum大于n的同时尽量小,相当于回溯
}
cout<<sum<<endl;
}
}
}