B3. 小朋友分糖果
Time limit per test: 1.0 seconds
Memory limit: 256 megabytes
有 n 个小朋友,标号为 1 到 n,每个小朋友有一些糖果,第 i 个小朋友拥有糖果数量为 ai。
为了使得每个小朋友拥有相同的糖果,现提供如下操作:选择两个小朋友组成一个有序对 (u,v) (1≤u,v≤n,u≠v),然后记两个小朋友拥有的糖果总和为 S,然后令 au=⌊S2⌋, av=⌈S2⌉。
即:
function do_something(u, v): S := (a[u] + a[v]) a[u] := floor(S / 2) a[v] := ceil(S / 2)
请构造一系列操作,使得所有小朋友最终拥有相同的糖果。
Input
第一行一个整数 n (1≤n≤1 000)。
第二行 n 个整数用空格隔开:a1,a2,…,an (0≤ai≤109)。
Output
题目保证有解。输出:
- 第一行:输出一个整数 m (0≤m≤10 000),表示操作序列的长度。
- 接下来依次输出操作,每一行输出两个整数 u,v,u,v 的含义见题意。
所以你的程序应该在 10 000 步以内完成任务。给定数据保证存在一种方案能够完成目标。你可以输出任意一种方案。
Examples
input
4 1 3 1 3
output
2 1 4 2 3
尽量每天做一道题以保持手感。
中文题意不解释。做法是每次取最大的和最小的进行处理。
那就很简单了。
这道题主要练了multiset的用法。erase可以用于删除某一些元素可以通过传迭代器和传值两种方法。
还有记住end()不是指向最后一个元素而是最后一个元素后一个位置。
STL大法好。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <set>
#include <map>
#include <set>
#include <vector>
#define vi vector<int>
#define ll long long
#define P pair<int,int>
using namespace std;
int main()
{
// freopen("out.txt","w",stdout);
ios::sync_with_stdio(false);
cin.tie(0);
multiset<node> q;
ll sum = 0;
cin >> n;
for(int i = 1; i <= n; i++)
{
int temp; cin >> temp;
sum += temp;
q.insert(node(temp, i));
}
int base = sum / n;
vector<P> ans;
while(!(q.begin()->a == base && q.rbegin()->a == base))
{
ans.push_back(P(q.begin()->idex, q.rbegin()->idex));
int au = q.begin()->a, av = q.rbegin()->a;
int aui = q.begin()->idex, avi = q.rbegin()->idex;
double temp = au + av;
q.erase(q.begin());
multiset<node> :: iterator ii = q.end();
ii--;
q.erase(ii);
q.insert(node(floor(temp / 2),aui));
q.insert(node(ceil(temp / 2),avi));
}
cout << ans.size() << endl;
for(auto i : ans)
cout << i.first << ' ' << i.second <<endl;
return 0;
}