#include <bits/stdc++.h>
using namespace std;
using namespace chrono;
using bvec = vector<bool>;
const int N = 10000, E = 100;
class timer: high_resolution_clock {
time_point start_time;
public:
inline timer () : start_time (now ()) {}
inline rep elapsed_time() const {
return duration_cast<milliseconds> (now () - start_time).count (); } };
inline int random_value(int min, int max) {
static mt19937_64 random(system_clock::now().time_since_epoch().count());
return uniform_int_distribution<int>(min,max)(random); }
struct random_positions: bvec {
inline random_positions(int n) : bvec(N+1,false) {
for (int x, count = 0; count < n; )
if (x = random_value(1,N), not at(x))
at(x) = true, ++count; } };
struct ivec: vector<int> {
ivec(int n) {
const random_positions used(n);
resize(n);
for (int i = 1, j = 0; i <= N and j < n; ++i)
if (used[i])
at(j++) = i; } };
struct distinct_distances: bvec {
int elapsed_time; const int n, m;
inline distinct_distances(const ivec &a) : n(a.size()), m(a.back()-a.front()) { resize(m+1,false); } };
struct unbounded: distinct_distances {
inline unbounded(const ivec &a) : distinct_distances(a) {
timer t;
for (int j = n-1; j > 0; --j)
for (int e = a[j], i = 0; i < j; ++i)
at(e-a[i]) = true;
elapsed_time = t.elapsed_time(); } };
struct bounded: distinct_distances {
inline bounded(const ivec &a) : distinct_distances(a) {
timer t;
for (int count = 0, j = n-1; j > 0 and count < m; --j)
for (int d, e = a[j], i = 0; i < j and count < m; ++i)
if (d = e-a[i], not at(d))
at(d) = true, ++count;
elapsed_time = t.elapsed_time(); } };
inline void write(const string &prompt, int time) { cout << prompt << " Time = " << time << " msec." << endl; }
int main() {
int t1 = 0, t2 = 0;
for (int e = 0; e < E; ++e) {
const int n = random_value(1,N);
const ivec a(n);
const unbounded s(a); const bounded t(a);
if (t1 += s.elapsed_time, t2 += t.elapsed_time, s != t)
throw logic_error("Distinct distances are not equal"); }
write("Unbounded",t1),
write(" Bounded",t2); }
I2luY2x1ZGUgPGJpdHMvc3RkYysrLmg+CnVzaW5nIG5hbWVzcGFjZSBzdGQ7CnVzaW5nIG5hbWVzcGFjZSBjaHJvbm87CnVzaW5nIGJ2ZWMgPSB2ZWN0b3I8Ym9vbD47CmNvbnN0IGludCBOID0gMTAwMDAsIEUgPSAxMDA7CgpjbGFzcyB0aW1lcjogaGlnaF9yZXNvbHV0aW9uX2Nsb2NrIHsKICAgIHRpbWVfcG9pbnQgc3RhcnRfdGltZTsKcHVibGljOgogICAgaW5saW5lIHRpbWVyICgpIDogc3RhcnRfdGltZSAobm93ICgpKSB7fQogICAgaW5saW5lIHJlcCBlbGFwc2VkX3RpbWUoKSBjb25zdCB7IAogICAgCXJldHVybiBkdXJhdGlvbl9jYXN0PG1pbGxpc2Vjb25kcz4gKG5vdyAoKSAtIHN0YXJ0X3RpbWUpLmNvdW50ICgpOyB9IH07CiAgICAJCmlubGluZSBpbnQgcmFuZG9tX3ZhbHVlKGludCBtaW4sIGludCBtYXgpIHsKCXN0YXRpYyBtdDE5OTM3XzY0IHJhbmRvbShzeXN0ZW1fY2xvY2s6Om5vdygpLnRpbWVfc2luY2VfZXBvY2goKS5jb3VudCgpKTsgCiAgICByZXR1cm4gdW5pZm9ybV9pbnRfZGlzdHJpYnV0aW9uPGludD4obWluLG1heCkocmFuZG9tKTsgfQoKc3RydWN0IHJhbmRvbV9wb3NpdGlvbnM6IGJ2ZWMgewoJaW5saW5lIHJhbmRvbV9wb3NpdGlvbnMoaW50IG4pIDogYnZlYyhOKzEsZmFsc2UpIHsKCQlmb3IgKGludCB4LCBjb3VudCA9IDA7IGNvdW50IDwgbjsgKQoJCQlpZiAoeCA9IHJhbmRvbV92YWx1ZSgxLE4pLCBub3QgYXQoeCkpCgkJCQlhdCh4KSA9IHRydWUsICsrY291bnQ7IH0gfTsKCnN0cnVjdCBpdmVjOiB2ZWN0b3I8aW50PiB7CglpdmVjKGludCBuKSB7CgkJY29uc3QgcmFuZG9tX3Bvc2l0aW9ucyB1c2VkKG4pOyAKCQlyZXNpemUobik7CgkJZm9yIChpbnQgaSA9IDEsIGogPSAwOyBpIDw9IE4gYW5kIGogPCBuOyArK2kpCgkJCWlmICh1c2VkW2ldKQoJCQkJYXQoaisrKSA9IGk7IH0gfTsKCQkJCQpzdHJ1Y3QgZGlzdGluY3RfZGlzdGFuY2VzOiBidmVjIHsKCWludCBlbGFwc2VkX3RpbWU7IGNvbnN0IGludCBuLCBtOwoJaW5saW5lIGRpc3RpbmN0X2Rpc3RhbmNlcyhjb25zdCBpdmVjICZhKSA6IG4oYS5zaXplKCkpLCBtKGEuYmFjaygpLWEuZnJvbnQoKSkgeyByZXNpemUobSsxLGZhbHNlKTsgfSB9OwoJCnN0cnVjdCB1bmJvdW5kZWQ6IGRpc3RpbmN0X2Rpc3RhbmNlcyB7CglpbmxpbmUgdW5ib3VuZGVkKGNvbnN0IGl2ZWMgJmEpIDogZGlzdGluY3RfZGlzdGFuY2VzKGEpIHsKCQl0aW1lciB0OwogICAgCWZvciAoaW50IGogPSBuLTE7IGogPiAwOyAtLWopCiAgICAgICAgCWZvciAoaW50IGUgPSBhW2pdLCBpID0gMDsgaSA8IGo7ICsraSkKICAgICAgICAJCWF0KGUtYVtpXSkgPSB0cnVlOyAKICAgICAgICBlbGFwc2VkX3RpbWUgPSB0LmVsYXBzZWRfdGltZSgpOyB9IH07CiAgICAgICAgICAgICAgICAKc3RydWN0IGJvdW5kZWQ6IGRpc3RpbmN0X2Rpc3RhbmNlcyB7CglpbmxpbmUgYm91bmRlZChjb25zdCBpdmVjICZhKSA6IGRpc3RpbmN0X2Rpc3RhbmNlcyhhKSB7CgkJdGltZXIgdDsKCQlmb3IgKGludCBjb3VudCA9IDAsIGogPSBuLTE7IGogPiAwIGFuZCBjb3VudCA8IG07IC0taikKICAgICAgICAJZm9yIChpbnQgZCwgZSA9IGFbal0sIGkgPSAwOyBpIDwgaiBhbmQgY291bnQgPCBtOyArK2kpCiAgICAgICAgCQlpZiAoZCA9IGUtYVtpXSwgbm90IGF0KGQpKQogICAgICAgIAkJCWF0KGQpID0gdHJ1ZSwgKytjb3VudDsgCiAgICAgICAgZWxhcHNlZF90aW1lID0gdC5lbGFwc2VkX3RpbWUoKTsgfSB9OwoJCmlubGluZSB2b2lkIHdyaXRlKGNvbnN0IHN0cmluZyAmcHJvbXB0LCBpbnQgdGltZSkgeyBjb3V0IDw8IHByb21wdCA8PCAiIFRpbWUgPSAiIDw8IHRpbWUgPDwgIiBtc2VjLiIgPDwgZW5kbDsgfQoJCmludCBtYWluKCkgewoJaW50IHQxID0gMCwgdDIgPSAwOwoJZm9yIChpbnQgZSA9IDA7IGUgPCBFOyArK2UpIHsKCQljb25zdCBpbnQgbiA9IHJhbmRvbV92YWx1ZSgxLE4pOyAKCQljb25zdCBpdmVjIGEobik7CgkJY29uc3QgdW5ib3VuZGVkIHMoYSk7IGNvbnN0IGJvdW5kZWQgdChhKTsKCQlpZiAodDEgKz0gcy5lbGFwc2VkX3RpbWUsIHQyICs9IHQuZWxhcHNlZF90aW1lLCBzICE9IHQpCgkJCXRocm93IGxvZ2ljX2Vycm9yKCJEaXN0aW5jdCBkaXN0YW5jZXMgYXJlIG5vdCBlcXVhbCIpOyB9Cgl3cml0ZSgiVW5ib3VuZGVkIix0MSksIAoJd3JpdGUoIiAgQm91bmRlZCIsdDIpOyB9Cg==