Mathematics
jzoj 1747
题目大意
有n堆石子,总和为2k2^k2k,现在对于两堆石子,你可以从a中取b的分量到b(a要大于b),问合成一堆大小为2k2^k2k的石子要怎么做(输出a,b)
输入样例
2 2
3 1
输出样例
2 1
1 2
数据范围
对于30%的数据,n=2;
对于100%的数据,n⩽100000,k⩽31。n\leqslant 100000,k\leqslant31。n⩽100000,k⩽31。
解题思路
既然总和就是最后一堆的大小那就是把所有合在一起啦
我们从小到大枚举二进制下的每一位,如果有1的那就找另一个有1的和他调一下,这样就可以清掉一位,我们不停清,最后就只剩2k2^k2k了
代码
#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;//乘上2printf("%lld %lld\n", s, j);}else{a[s] -=a[j];a[j] <<= 1;printf("%lld %lld\n", j, s);}p = 0;}}return 0;
}