G - Eva's Balance (3進制&數論)

G - Eva’s Balance (3進制&數論)

題意:給202033的冪次方數:30,31,323193^0,3^1,3^2\dots3^{19}和一個數nn,要求用這2020個數中若干個使左右兩個秤盤數之和相等.
nn開始被放在左盤)

思路:因爲都是33的冪次方,題目等價於構造兩個33的冪次方之和相減等於nn,所以考慮33進制下來表示nn.

所以nn被轉化爲0,1,20,1,2的數字串。當該位posipos_i010或1時,顯然可以不會用到3i3^{i}或者直接抵消掉。

posi=2pos_i=2時,因爲2×3i=3×3i3i=3i+13i2\times 3^i=3\times3^i-3^i=3^{i+1}-3^i。所以等價於posi+1+1pos_{i+1}+1然後posi=1pos_i=-1

posi=3pos_i=3時,顯然3×3i=3i+13\times 3^i=3^{i+1},所以等價於posi+1+1,posi=0pos_{i+1}+1,pos_i=0.然後再根據pospos的正負情況,將負的給左盤,正的給右盤,此題就解決了。

時間複雜度:O(log3n×log2n)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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章