给出一个重物重量为X,另外提供的小砝码重量分别为1,3,9。。。3^N。 将重物放到天平左侧,问在两边如何添加砝码使两边平衡。 假设N无限大,但一种重量的砝码只有一个)

先将物体的重量用三进制表示,例如47为1202,将物体放在天枰的左边,下面就让三进制中每位为2的变为0或者1,那么就给天枰左边加 1砝码一个这时左边1210,再往左边加一个9砝码这时左边为2010,再往左边加一个砝码27这时左边为10010,那么右边加上砝码81和砝码3,那么天枰就平衡了。
推广至n即可,将三进制中的2变为0就行了。 

当3^0+3^1.。。。+3^n<N时则无解。

即转化为三进制 从最低位开始 
1.遇到0 无操作 
2.遇到1 右边放  
3.遇到2 左边放 然后进位 
扫描完一遍 就完了 

1. 3^N 
2. x = 3m , x = 3m +1 ,x = 3m+2  (1,3,9....) 
   2.1 x = 3m +1  右侧放1  x1 = 3m 
   2.2 x = 3m +2  左边放1  x2 = 3(m+1) = 3k (3,9...) 
   -> x = 3z (3,9,27...) 
   x = z; 递归上诉1和2式子 
  
  
47 = 3*16-1 左侧放1 -> 3*16 
3*16 =3*(3*5+1) 右侧放 3*1 ->3*3*5 
3*3*(6-1) 左侧加上3*3*1 -> 3**6 
3*3*3*(3-1) 左侧放 3*3*3 -> 3*3*3*3 
3*3*3*3 右侧放上 3^4 
所以得到 47+1 + 9+ 27 = 3+ 81 

#include <stdio.h> 
#include <math.h> 
  
int find(int x, int *a,int *b,int *aLen, int *bLen) 
{ 
     int t = x%3; 
     int count = 0; 
     while(x > 0) 
     { 
         if(t == 2) 
         { 
             *a = count; 
             a++;     
             x+=1; 
             (*aLen)++; 
         }else if( t == 1) 
         { 
             *b = count; 
             b++; 
             (*bLen)++; 
         } 
         count++; 
         x= x/3; 
         t = x%3; 
     } 
  
     return 0; 
} 
  
int main() 
{ 
     int a[100]; 
     int b[100]; 
     int aLen = 0; 
     int bLen = 0; 
     int n,i; 
     int sum = 0; 
     scanf("%d",&n); 
     find(n,a,b,&aLen,&bLen); 
     for( i = 0; i < aLen; i++ ) 
     { 
         printf("%d ",a[i]); 
         sum += (int)pow(3.0,a[i]); 
     } 
     printf("\nsum = %d\n",sum+n); 
     sum = 0; 
     for( i = 0; i < bLen; i++ ) 
     { 
         printf("%d ",b[i]); 
         sum += (int)pow(3.0,b[i]); 
     } 
     printf("\nsum = %d\n",sum); 
}  
balance函数的返回值永远是true,因为任意一个正整数都可以表示为三进制 
  
/** 
      * @param weight    重物的重量,应该是一个正整数 
      * @return 是否可使得天秤平衡 
      */ 
     public static boolean balance(int weight) { 
         int origin = weight;        //备份 
         int left = 0;        //左边放了什么砝码 
         int right = 0;        //右边放了什么砝码 
         int i = 0;        //当前位是0是1还是2。0是最低位 
         while (weight != 0) { 
             int tmp = weight % 3;         
             if (tmp == 2) { 
                 weight += 1; 
                 left = left | (1 << i);        //对应的二进制位置1 
             } else if (tmp == 1) { 
                 right = right | (1 << i); 
             } 
             i++; 
             weight /= 3; 
         } 
          
         //上面已经求得答案了,现在输出验证一下 
         StringBuilder sbLeft = new StringBuilder("" + origin); 
         int sumLeft = origin; 
         if (left != 0) { 
             int power = 1; 
             while (left != 0) { 
                 int value = left & 1; 
                 if (value == 1) { 
                     sbLeft.append(" + " + power); 
                     sumLeft += power; 
                 } 
                 power *= 3; 
                 left = left >> 1; 
             } 
         } 
          
         int sumRight = 0; 
         StringBuilder sbRight = new StringBuilder(); 
         if (right != 0) { 
             int m = 1; 
             while (right != 0) { 
                 int value = right & 1; 
                 if (value == 1) { 
                     sbRight.append(" + " + m); 
                     sumRight += m; 
                 } 
                 m *= 3; 
                 right = right >> 1; 
             } 
         } 
         System.out.println(sbLeft.toString() + " = " + sbRight.substring((" + ").length()).toString()); 
         System.out.println(sumLeft + "," + sumRight); 
         return sumLeft == sumRight; 
          
     } 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值