Mathematics

MathematicsMathematics

題目鏈接:jzoj 1747

題目

nn堆石子,從1 n1~n編號,其石子總數爲2k2^k。每次可以選擇兩堆石子aabb,滿足aa堆的石子數不比bb堆的多,記ccaa的石子數。然後可以進行以下操作:從bb堆石子中拿cc這麼多的石子到aa堆中。要求你給出一個方案,使得最後有一堆石子的數目達到2k2^k

輸入

第一行兩個正整數nnkk
第二行nn個非負數aiai

輸出

輸出若干行,每行兩個數aabb,表示每次操作中的兩堆石子的編號,必須滿足題中所給的大小關係!

樣例輸入

2 2
3 1

樣例輸出

2 1
1 2

數據範圍

對於30%30\%的數據,n=2n=2
對於100%100\%的數據,n<=100000n<=100000k<=31k<=31

思路

這道題是一道暴力。
我們要讓其中一個數變爲2k2^k,其實就是然其它數都爲00
那麼,我們可以枚舉從低到高每一位,把這一位不爲零的數成對的進行操作。因爲經過操作之後,這兩個數的這一位都會變成零。(判斷這個數某一位是否爲00可以用位運算解決)
然後就可以了。

代碼

#include<cstdio>

using namespace std;

int n, k, a[100001], t;

int main() {
	scanf("%d %d", &n, &k);//讀入
	for (int i = 1; i <= n; i++)
		scanf("%d", &a[i]);//讀入
	
	for (int i = 1; i <= k; i++)
		for (int j = 1; j <= n; j++)
			if (a[j] & (1 << (i - 1))) {//這一位還是1
				if (!t) t = j;//沒有找到另一半
					else {
						if (a[t] < a[j]) {//左邊的比右邊大
							printf("%d %d\n", t, j);
							a[j] -= a[t];
							a[t] *= 2;
							t = 0;
						}
						else {//右邊的比左邊大或者一樣大
							printf("%d %d\n", j, t);
							a[t] -= a[j];
							a[j] *= 2;
							t = 0;
						}
					}
			}
		
	
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章