# Bit Manipulation# Greedy# Two's Complement

e455 - 二進位的絕對值

🔗 前往 ZeroJudge 原題

題目描述

題目給定一個 16 位元的二進位整數,要求輸出其十進位絕對值。題目限制不能使用 <bitset>,並強調考驗演算法和優化。

解題思路

這題的核心在於理解二進位的絕對值計算。由於輸入是 16 位元的二進位數,我們可以將其視為一個有號整數。如果最高位是 0,則直接將二進位數轉換為十進位即可。如果最高位是 1,則表示該數為負數,需要計算其二補數,然後取絕對值。二補數的計算方式是將所有位元反轉,然後加 1。然而,程式碼中採用了更簡潔的方式:如果最高位是 1,則將其視為負數,直接用 32768 (2^15) 減去其正數表示的值,即可得到其絕對值。

程式碼使用 getchar_unlocked() 逐一讀取二進位位元,並使用位移運算 k >>= 1 來計算每個位元的權重。write() 函數用於輸出十進位結果,它避免了使用標準輸出流,以提高效率。

複雜度分析

  • 時間複雜度: O(16) (因為輸入固定為 16 位元)
  • 空間複雜度: O(1) (使用固定大小的陣列 stk 來儲存十進位數字)

程式碼

#pragma GCC optimize("Ofast,unroll-loops,no-stack-protector,fast-math")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#include <stdio.h>
inline void write(int x) {
	if(x==0)putchar_unlocked('0');
	int stk[5],*ptr(&stk[0]);
	while(x){*ptr=x%10;x/=10;++ptr;}
	while(--ptr>=(&stk[0])){putchar_unlocked(*ptr+'0');}
}
char a,a0;
int main(){
	while(a0=getchar_unlocked()){
		if(a0==EOF)break;
		int ans(0);
		for(int i(1),k(16384);i<16;++i,k>>=1){
			a=getchar_unlocked();
			if(a=='1')ans+=k;
		}
		if(a0=='1')ans=32768-ans;
		write(ans);
		putchar_unlocked('\n');
		a0=getchar_unlocked();
	}
}

Discussion