Mathematics(jzoj 1747)

Mathematics

jzoj 1747

題目大意

有n堆石子,總和爲2k2^k,現在對於兩堆石子,你可以從a中取b的分量到b(a要大於b),問合成一堆大小爲2k2^k的石子要怎麼做(輸出a,b)

輸入樣例

2 2
3 1

輸出樣例

2 1
1 2

數據範圍

對於30%的數據,n=2;
對於100%的數據,n100000k31n\leqslant 100000,k\leqslant31。

解題思路

既然總和就是最後一堆的大小那就是把所有合在一起啦
我們從小到大枚舉二進制下的每一位,如果有1的那就找另一個有1的和他調一下,這樣就可以清掉一位,我們不停清,最後就只剩2k2^k

代碼

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
ll n, k, p, s, a[100500];
int main()
{
	scanf("%lld %lld", &n, &k);
	for (ll i = 1; i <= n; ++i)
		scanf("%lld", &a[i]);
	for (ll sum = 1, i = 0; i < k; ++i, sum <<= 1)//每一位
		for (ll j = 1; j <= n; ++j)
			if (a[j]&sum)
			{
				if (!p)//沒有前面一個先記錄下來
					s = j, p = 1;
				else
				{
					if (a[j] > a[s])//有前面一個就要判斷誰給誰
					{
						a[j] -= a[s];//給他那麼多就減掉那麼多
						a[s] <<= 1;//乘上2
						printf("%lld %lld\n", s, j);
					}
					else
					{
						a[s] -=a[j];
						a[j] <<= 1;
						printf("%lld %lld\n", j, s);
					}
					p = 0;
				}
			}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章