有n堆石子,石子總數爲2k, 現在需要對每兩個石子進行一次操作,使得最後只有一堆石子,也就是一堆有2k個石子,此操作爲對於兩堆石子x和y,x堆的石子數不大於y堆的石子數,然後將x堆那麼多的石子從y堆取出並放入x堆。現在要你求出這個方案
第一行兩個正整數n,k
第二行n個非負數ai。
輸出若干行,每行兩個數x,y,表示每次操作中的兩堆石子的編號
2 2
3 1
2 1
1 2
對於30%的數據,n=2;
對於100%的數據,n<=100000,k<=31。
因爲只要是可行的方案就行
所以直接暴力就好
整個石子可以看成二進制
當只剩最後一堆時
二進制就是一個1,k個0
所以我們可以把整個二進制
從低到高
把每一位都先變爲0
最後只剩最後一堆
我們需要判斷這個二進制某一位是否爲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;
}