poj 1702
问题描述:
有一个天平和20个砝码,砝码的重量分别为1, 3, 9, 27,...,3^19,要求合理地把其中某些砝码放到天平的两边,测量出给定物体的重量w(1<w<(3^20-1)/2),待测物体放置在天平的左侧。
分析
左侧砝码总重+物体重量=右侧砝码总重
物体重量=右侧砝码总重-左侧砝码总重
所以,问题可以转化为:给出正整数w,对3^i(0<=i<=19)加上权值s (s=-1,0或者1),使得所有项的总和为w。s=-1对应于砝码放在天平左侧,s=1对应于砝码放在天平右侧,s=0对应于不使用该砝码。列举前10项的情形如下:
通过观察,这个表格和基数为3的“进位制”问题很像(如果对最基础的进位制问题的原理和方法不清楚,建议先了解一下)。我们不妨定义映射f : {0,1,2}-->{0,1,-1},即可将n%3的值相应转换为这里所要求的权值。这里还有一个问题,除第一项以外,之后每一项的“第一个周期”都是不完全的,所以对迭代过程中的n=n/3要作一个修正,考察图中的5,6,7,这三个数的后几项和2相同(红框所示),所以迭代过程应该将5,6,7转换到2,同理2,3,4-->1,8,9,10-->3等等,n=n/3最后修正为n=(n+1)/3。
核心代码
index = 0;
int table[3] = {0,1,-1};
while (n) {
num[index] = table[n%3];
n = (n+1)/3;
index++;
}
// 1702.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include<iostream> using namespace std; int main() { int N; cin>>N; int num[20]; int table[3]={0,1,-1}; long long pow3[64]; pow3[0]=1; for(int i=1;i<64;i++) pow3[i]=pow3[i-1]*3; while(N--) { memset(num,0,20*sizeof(num[0])); int nums; cin>>nums; int index=0; while(nums) { num[index]=table[nums%3]; nums=(nums+1)/3; index++; } bool flag=false; int count=1; for(int i=0;i<index;i++) { if(num[i]==-1) { flag=true; if(count==1) cout<<pow3[i]; else cout<<","<<pow3[i]; count++; } } if(!flag) cout<<"empty"<<" "; else cout<<" "; count=1; for(int i=0;i<index;i++) { if(num[i]==1) { if(count==1) cout<<pow3[i]; else cout<<","<<pow3[i]; count++; } } cout<<endl; } system("pause"); return 0; }