Mathematics【JZOJ】

DescriptionDescription

有n堆石子,石子總數爲2k, 現在需要對每兩個石子進行一次操作,使得最後只有一堆石子,也就是一堆有2k個石子,此操作爲對於兩堆石子x和y,x堆的石子數不大於y堆的石子數,然後將x堆那麼多的石子從y堆取出並放入x堆。現在要你求出這個方案

InputInput

第一行兩個正整數n,k
第二行n個非負數ai。

OutputOutput

輸出若干行,每行兩個數x,y,表示每次操作中的兩堆石子的編號

SampleSample InputInput

2 2
3 1

SampleSample OutputOutput

2 1
1 2

HintHint

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

TrainTrain ofof ThoughtThought

因爲只要是可行的方案就行
所以直接暴力就好
整個石子可以看成二進制
當只剩最後一堆時
二進制就是一個1,k個0
所以我們可以把整個二進制
從低到高
把每一位都先變爲0
最後只剩最後一堆
我們需要判斷這個二進制某一位是否爲1時
就直接A[j]A[j] & (1<<(i1))(1 << (i - 1))
因爲是從高到低
所以二進制中最高位以後肯定是0
如果答案爲1則第i位1
答案爲0則相反

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#define ll long long
using namespace std;
ll A[100250]; 
int n, m, t;
int main()
{
	scanf("%d%d", &n, &t);
	for(int i = 1; i <= n ; ++i)scanf("%lld", &A[i]);
	for(int i = 1; i <= t; i++)
	{
		int x = 0, y = 0;
		for(int j = 1; j <= n; j++)
			if(A[j] & (1 << (i - 1)))
			{
				if(x)
				{
					y = j;
					if(A[x] < A[y])
					{
						printf("%d %d\n", x, y);
						ll l = A[x];
						A[x] *= 2;
						A[y] -= l;
					}
					else
					{
						printf("%d %d\n", y, x);
						ll l = A[y];
						A[y] *= 2;
						A[x] -= l;
					}
					x = y = 0;
				}
				else x = j;
			}
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章