G - Eva's Balance (3进制&数论)

题意:给的幂次方数:和一个数,要求用这个数中若干个使左右两个秤盘数之和相等.
开始被放在左盘)

思路:因为都是的幂次方,题目等价于构造两个的幂次方之和相减等于,所以考虑进制下来表示.

所以被转化为的数字串。当该位时,显然可以不会用到或者直接抵消掉。

时,因为。所以等价于然后

时,显然,所以等价于.然后再根据的正负情况,将负的给左盘,正的给右盘,此题就解决了。

时间复杂度:

AC代码:

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
using namespace std;
typedef long long ll;
const int N=2e3+5,inf=0x3f3f3f3f;
int a[N],n,t;
#define mst(a) memset(a,0,sizeof a)
int ksm(int a,int n){ //快速幂板子. 
    int ans=1;
    while(n){
        if(n&1) ans=ans*a;
        a=a*a;
        n>>=1;
    }
    return ans;
}
int main(){
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        mst(a);
        int k=0;
        while(n){ //转换为三进制. 
            a[++k]=n%3;
            n/=3;
        }
        int f1=0,f2=0;//用来控制格式(逗号) 
        for(int i=1;i<=k+1;i++){ //重点转换. 
            if(a[i]==2) a[i]=-1,a[i+1]++;
            else if(a[i]==3) a[i]=0,a[i+1]++;
        }
        for(int i=1;i<=k+1;i++){ //输出 注意是可能k+1位. 
            if(a[i]==-1){
                if(f1) printf(",%d",ksm(3,i-1));
                else f1=1,printf("%d",ksm(3,i-1));
            }
        }
        if(!f1) printf("empty");
        printf(" ");
        for(int i=1;i<=k+1;i++){
            if(a[i]==1){
                if(f2) printf(",%d",ksm(3,i-1));
                else f2=1,printf("%d",ksm(3,i-1));
            }
        }
        if(!f2) printf(" empty");
        puts("");
    }
    return 0;
}