Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 3906 | Accepted: 1924 |
Description
Eva has a balance with 20 poises. The weights of the poises are 1, 3, 9, 27,...,3^19. Eva asserts that she has a way to measure any object whose weight is an integer from 1 to (3^20-1)/2. Assuming that Eva has placed an object with the weight in this range on the left tray of the balance, your task is to place the proper poises on the proper trays so as to weigh the object out.
Input
The first line is an integer T (1 <= T <= 20), which shows the number of the test cases. Each of the following T lines contains an integer W (1 <= W <= (3^20-1)/2), expressing the weight of an object.
Output
For each test case print a line, showing the weights of the poises on the left tray and the right tray. Use a space to separate the left tray and the right tray. The poises on the same tray are arranged in the increasing order, and a comma separates every two of them. If there is no poise on the tray, output "empty".
Sample Input
3
9
5
20
Sample Output
empty 9
1,3 9
1,9 3,27
Source
#include <iostream>
#include <string.h>
#include <stdio.h> using namespace std; int main()
{
int data[]; ///存打表的数的
int ans[]; ///存输出的数的
int a[]; ///存三进制数的
for(int i=,n=; i<=; i++,n*=)
data[i]=n; int t;
scanf("%d",&t);
while(t--)
{
int nn;
scanf("%d",&nn);
memset(ans,,sizeof(ans));
memset(a,,sizeof(a));
int cnt=;
while(nn)
{
a[++cnt]=nn%;
nn/=;
}
for(int i=; i<=cnt; i++)
{
if(a[i]==) a[i+]++,a[i]=-;
if(a[i]==) a[i+]++,a[i]=;
}
if(a[cnt+]) cnt++; bool flag=false;
int tp=;
for(int i=; i<=cnt; i++)
{
if(a[i]<)
flag=true,ans[++tp]=data[i-];
}
if(!flag)
printf("empty ");
else
{
for(int i=; i<tp; i++)
{
printf("%d,",ans[i]);
}
printf("%d ",ans[tp]);
}
flag=false;
tp=;
for(int i=; i<=cnt; i++)
{
if(a[i]>)
flag=true,ans[++tp]=data[i-];
}
if(!flag)
{
printf("empty ");
}
else
{
for(int i=; i<tp; i++)
{
printf("%d,",ans[i]);
}
printf("%d",ans[tp]);
}
puts("");
}
return ;
}
分析:本题用到了很冷的平衡三进制算法
首先我们可以将数n分解成三进制加法形式
e.g 102=(01201) i.e 102=0*3(0)+1*3(1)+2*3(2)+0*3(3)+1*3(4)
有如下转换:
2*3(n)=(3-1)*3(n)=3(n+1)-3(n)
这样,我们便可以用-1,0,1表示一个数字。同时1,-1也构成了两堆三进制数。
\(^o^)/,问题解决。
p.s:有一些细节我在代码中注释了。
#include "iostream"
#include "cstring"
#include "cstdlib"
#include "cstdio"
#include "cmath"
using namespace std;
int n;
int a[100001],tp;
int sto[10001],cnt;
int data[100];
int main(){
//freopen("ans.txt","r",stdin);
//freopen("1.txt","w",stdout);
for (int i=0,tt=1;i<=99;i++,tt*=3) data[i]=tt;
int cases;scanf("%d",&cases);
while(cases--){
scanf("%d",&n);tp=0;
memset(sto,0,sizeof sto); //忘了清数组,贡献2wa
memset(a,0,sizeof a);
while(n){
a[++tp]=n%3;
n/=3;
}
while(1);
for (int i=1;i<=tp;i++){ //转化为平衡三进制。
if (a[i]==2) a[i]=-1,a[i+1]++;
if (a[i]==3) a[i]=0,a[i+1]++;
}
bool flag=false;
if (a[tp+1]) tp++; //如果加过了,tp++
cnt=0;
for (int i=1;i<=tp;i++) //处理减数
if (a[i]<0) flag=true,sto[++cnt]=data[i-1];
if (!flag) printf("empty "); //不存在减数
else {for (int i=1;i<cnt;i++) printf("%d,",sto[i]);printf("%d ",sto[cnt]);}
flag=false;cnt=0;
for (int i=1;i<=tp;i++) //处理减数
if (a[i]>0) flag=true,sto[++cnt]=data[i-1];
if (!flag) printf("empty"); //不存在被减数,其实就是对0,0这个case的处理。
else {for (int i=1;i<cnt;i++) printf("%d,",sto[i]);printf("%d",sto[cnt]);}
a[tp]=0;
puts("");
} return 0;
}
/*
301354
3,729,59049,177147 1,9,27,243,6561,531441
*/