#include "message.h"
#include "futbol.h"
#include <cstdio>
#include <vector>
using namespace std;
typedef long long LL;
int n, k, p;
LL psum(LL a, LL b) {
return (a+b) % p;
}
LL pmul(LL a, LL b) {
return (a*b) % p;
}
LL ppow(LL a, LL b) {
if (b == 0) return 1;
LL r = ppow(pmul(a, a), b/2);
if (b&1) return pmul(r, a);
return r;
}
LL pinv(LL a) {
return ppow(a, p-2);
}
void FillBottom(vector<LL>& e, int a, int b) {
LL f = 1;
for (int i=a; i<b; ++i) {
if (i == 0) continue;
f = pmul(f, pinv(i));
e[i-a] = f;
}
}
void FillTop(vector<LL>& e, int a, int b) {
LL f = 1;
for (int i=a; i<b; ++i) {
if (i == 0) continue;
f = pmul(f, n-i+1);
e[i-a] = pmul(e[i-a], f);
}
}
LL Sum(const vector<LL>& e, int a, int b, LL f) {
LL sum = 0;
for (LL x : e) {
sum += pmul(x, f);
}
return sum % p;
}
int main() {
n = GetN();
k = GetK(); ++k;
p = GetP();
int nodes = NumberOfNodes();
int node_id = MyNodeId();
int next_node_id = (node_id + 1) % nodes;
int prev_node_id = (node_id + nodes - 1) % nodes;
int a = k * node_id / nodes;
int b = k * (node_id + 1) / nodes;
vector<LL> e(b-a, 1);
FillBottom(e, a, b);
if (n != 0) {
FillTop(e, a, b);
}
LL f = 1;
LL sum = 0;
if (node_id == 0) {
sum = Sum(e, a, b, f);
if (!e.empty()) {
f = pmul(f, e.back());
}
PutLL(next_node_id, n);
PutLL(next_node_id, f);
PutLL(next_node_id, sum);
Send(next_node_id);
Receive(prev_node_id);
GetLL(prev_node_id); // n
GetLL(prev_node_id); // f
printf("%lld\n", GetLL(prev_node_id)); // sum
} else {
Receive(prev_node_id);
if (n != 0) {
GetLL(prev_node_id); // n
} else {
n = GetLL(prev_node_id);
FillTop(e, a, b);
}
f = GetLL(prev_node_id);
sum = GetLL(prev_node_id);
sum = (sum + Sum(e, a, b, f)) % p;
if (!e.empty()) {
f = pmul(f, e.back());
}
PutLL(next_node_id, n);
PutLL(next_node_id, f);
PutLL(next_node_id, sum);
Send(next_node_id);
}
return 0;
}
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 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | #include "message.h" #include "futbol.h" #include <cstdio> #include <vector> using namespace std; typedef long long LL; int n, k, p; LL psum(LL a, LL b) { return (a+b) % p; } LL pmul(LL a, LL b) { return (a*b) % p; } LL ppow(LL a, LL b) { if (b == 0) return 1; LL r = ppow(pmul(a, a), b/2); if (b&1) return pmul(r, a); return r; } LL pinv(LL a) { return ppow(a, p-2); } void FillBottom(vector<LL>& e, int a, int b) { LL f = 1; for (int i=a; i<b; ++i) { if (i == 0) continue; f = pmul(f, pinv(i)); e[i-a] = f; } } void FillTop(vector<LL>& e, int a, int b) { LL f = 1; for (int i=a; i<b; ++i) { if (i == 0) continue; f = pmul(f, n-i+1); e[i-a] = pmul(e[i-a], f); } } LL Sum(const vector<LL>& e, int a, int b, LL f) { LL sum = 0; for (LL x : e) { sum += pmul(x, f); } return sum % p; } int main() { n = GetN(); k = GetK(); ++k; p = GetP(); int nodes = NumberOfNodes(); int node_id = MyNodeId(); int next_node_id = (node_id + 1) % nodes; int prev_node_id = (node_id + nodes - 1) % nodes; int a = k * node_id / nodes; int b = k * (node_id + 1) / nodes; vector<LL> e(b-a, 1); FillBottom(e, a, b); if (n != 0) { FillTop(e, a, b); } LL f = 1; LL sum = 0; if (node_id == 0) { sum = Sum(e, a, b, f); if (!e.empty()) { f = pmul(f, e.back()); } PutLL(next_node_id, n); PutLL(next_node_id, f); PutLL(next_node_id, sum); Send(next_node_id); Receive(prev_node_id); GetLL(prev_node_id); // n GetLL(prev_node_id); // f printf("%lld\n", GetLL(prev_node_id)); // sum } else { Receive(prev_node_id); if (n != 0) { GetLL(prev_node_id); // n } else { n = GetLL(prev_node_id); FillTop(e, a, b); } f = GetLL(prev_node_id); sum = GetLL(prev_node_id); sum = (sum + Sum(e, a, b, f)) % p; if (!e.empty()) { f = pmul(f, e.back()); } PutLL(next_node_id, n); PutLL(next_node_id, f); PutLL(next_node_id, sum); Send(next_node_id); } return 0; } |
English