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

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

题意:给 20 20 3 3 的幂次方数: 3 0 , 3 1 , 3 2 3 19 3^0,3^1,3^2\dots3^{19} 和一个数 n n ,要求用这 20 20 个数中若干个使左右两个秤盘数之和相等.
n n 开始被放在左盘)

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

所以 n n 被转化为 0 , 1 , 2 0,1,2 的数字串。当该位 p o s i pos_i 0 1 0或1 时,显然可以不会用到 3 i 3^{i} 或者直接抵消掉。

p o s i = 2 pos_i=2 时,因为 2 × 3 i = 3 × 3 i 3 i = 3 i + 1 3 i 2\times 3^i=3\times3^i-3^i=3^{i+1}-3^i 。所以等价于 p o s i + 1 + 1 pos_{i+1}+1 然后 p o s i = 1 pos_i=-1

p o s i = 3 pos_i=3 时,显然 3 × 3 i = 3 i + 1 3\times 3^i=3^{i+1} ,所以等价于 p o s i + 1 + 1 , p o s i = 0 pos_{i+1}+1,pos_i=0 .然后再根据 p o s pos 的正负情况,将负的给左盘,正的给右盘,此题就解决了。

时间复杂度: O ( l o g 3 n × l o g 2 n ) O(log_3n\times log_2n)

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;
}
原创文章 201 获赞 165 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_45750972/article/details/106041833
今日推荐