#UVa:11121-Base -2

灆洢 2012-01-17 14:31:45

這題可以先將輸入的數字的絕對值換成2進位制,例如:7 => 111、-7 => 111。再來從小到大看看它由哪些2的幾次方組成,如果該次方與輸入的數字同號時,換成base(-2)的時候,也一樣會有該次方;如果該次方與輸入的數字不同號時,換成base(-2)的時候,就需要該次方與該次方+1兩個所組成。

例如:7 = 111 有2^0、2^1、2^2。

  • 2^0 -> (-2)^0 直接換過來即可。
  • 2^1 -> ((-2)^1 + (-2)^2) 該次方+該次方的下一個次方即可組成。
  • 2^2 -> (-2)^2 直接換過來即可。

加起來會有 1個(-2)^0,1個(-2)^1,2個(-2)^2,2個(-2)^2要進位,但是對於base(-2)又得再利用(-2)^3+(-2)^4才能組起來,所以答案就會是 11011 。

P.S. 進位的地方用or運算是因為當你發覺要有2個(-2)^奇數次方(假設a)時(以N為正數為例,反之則反),根據上述做法要用2個(-2)^(a+1)次方和2個(-2)^a,2個(-2)^(a+1)和2個(-2)^a = 1個(-2)^(a+1) + 0個(-2)^a,而(-2)^a次方會因為%(Mod)的關係變為0,而進位只需要確定要不要就可以了,如此才使用or。

C++(0.084)

/*******************************************************/
/* UVa 11121 Base -2                                   */
/* Author: Maplewing [at] knightzone.studio            */
/* Version: 2012/01/17                                 */
/*******************************************************/
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;

int main(){
  int N, num, carry, sign, digit;
  while( scanf( "%d", &N ) != EOF ){
    for( int x = 1 ; x <= N ; x++ ){
      scanf( "%d", &num );
      printf( "Case #%d: ", x );
      if( num == 0 ){
        printf( "0\n" );
        continue;
      }

      int bits[50] = {0};
      sign = num;
      num = abs(num);
      digit = 0;
      while( num ){
        bits[digit++] = num%2;
        num /= 2;
      }

      carry = 0;
      for( int i = 0 ; i < digit || carry ; i++ ){
        if( i >= digit ) digit = i+1;
        bits[i] += carry;
        carry = 0;
        if( i%2 && (sign > 0) && bits[i] ){
          carry |= 1;
          digit = max( digit, i+2 );
        }
        else if( !(i%2) && (sign < 0) && bits[i] ){
          carry |= 1;
          digit = max( digit, i+2 );
        }
        carry = carry || bits[i] / 2;
        bits[i] %= 2;
      }

      for( int i = digit-1 ; i >= 0 ; i-- )
        printf( "%d", bits[i] );
      printf( "\n" );
    }
  }
  return 0;
}

發表迴響

這個網站採用 Akismet 服務減少垃圾留言。進一步瞭解 Akismet 如何處理網站訪客的留言資料