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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章