1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#include <algorithm>
#include <cstdio>
#include <vector>
#include "skup.h"
#include "message.h"
using namespace std;

#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define REP(i,n) FOR(i,0,n)
#define VAR(v,w) __typeof(w) v=(w)
#define FORE(it,c) for(VAR(it,(c).begin());it!=(c).end();++it)
#define PB push_back
#define ALL(c) (c).begin(),(c).end()
#define SIZE(c) ((int)(c).size())

typedef long long LL;
typedef vector<int> VI;
typedef vector<bool> VB;

int nodes, node;
VI blocks[100];
bool have[100];
int already;

VB share(int id) {
	LL m1 = 0, m2 = 0;
	if (id >= 0) {
		if (id >= 50) m2 = 1LL << (id - 50);
		else m1 = 1LL << id;
	}
	REP(i,nodes-1) {
		REP(j,nodes) if (j != node) {
			PutLL(j, m1);
			PutLL(j, m2);
			Send(j);
		}
		REP(j,nodes) if (j != node) {
			Receive(j);
			m1 |= GetLL(j);
			m2 |= GetLL(j);
		}
	}
	VB shared(nodes);
	REP(i,min(nodes,50)) shared[i] = (m1 >> i) & 1;
	FOR(i,50,nodes) shared[i] = (m2 >> (i - 50)) & 1;
	return shared;
}

void sendBlock(int t, int f) {
	PutInt(t, f + 1);
	PutInt(t, SIZE(blocks[f]));
	REP(i,1000) PutInt(t, i < SIZE(blocks[f]) ? blocks[f][i] : 0);
	Send(t);
}

int getBlock() {
	int s = Receive(-1);
	int f = GetInt(s) - 1;
	int size = GetInt(s);
	VI block(1000);
	REP(i,1000) block[i] = GetInt(s);
	if (f < 0 || have[f]) return -1;
	block.resize(size);
	swap(block, blocks[f]);
	have[f] = 1;
	++already;
	return f;
}

int main() {
	nodes = NumberOfNodes();
	node = MyNodeId();
	bool master = 0;
	VB visible = share(node);
	int known = count(ALL(visible), true);
	if (known == nodes) {
		VB seers = share(node);
		if (find(ALL(seers), true) - seers.begin() == node) master = 1;
	} else share(-1);
	int n = NumberOfCompanies();
	blocks[node].resize(n);
	REP(i,n) blocks[node][i] = GetShareCost(i);
	have[node] = 1;
	already = 1;
	REP(i,nodes) if (i != node) sendBlock(i, node);
	while (already < known) {
		int f = getBlock();
		if (f >= 0) REP(i,nodes) if (i != node) sendBlock(i, f);
	}
	if (!master) return 0;
	VI c;
	REP(i,nodes) FORE(it,blocks[i]) c.PB(*it);
	sort(ALL(c));
	int cc = SIZE(c);
	LL res = 0;
	REP(i,cc) res += LL(cc - i) * c[i];
	printf("%lld\n", res);
}