#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
static unsigned fast_mod(uint64_t x, unsigned m) {
// Optimized mod for Codeforces 32-bit machines.
// x must be less than 2^32 * m for this to work, so that x / m fits in an unsigned 32-bit int.
unsigned x_high = unsigned(x >> 32), x_low = unsigned(x);
unsigned quot, rem;
asm("divl %4\n"
: "=a" (quot), "=d" (rem)
: "d" (x_high), "a" (x_low), "r" (m));
return rem;
}
class Timer {
std::chrono::time_point<std::chrono::steady_clock> timePoint;
size_t value;
public:
void start() { timePoint = std::chrono::steady_clock::now(); }
void finish() {
auto curr = std::chrono::steady_clock::now();
auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(curr - timePoint);
value = elapsed.count();
}
size_t operator()() const { return value; }
} timer;
uint32_t x32 = 314159265;
uint32_t xorshift32()
{ // fastest random generator
x32 ^= x32 << 13;
x32 ^= x32 >> 17;
x32 ^= x32 << 5;
return x32;
}
int main() {
unsigned mod; std::cin >> mod;
std::vector<uint32_t> data(1 << 16);
for (auto& it : data) it = xorshift32();
timer.start();
uint32_t prod=1;
for (int iter = 0; iter < 1000; iter++) {
for (auto it : data) {
prod = fast_mod(uint64_t(prod)*it,mod);
}
}
timer.finish();
std::cout << "prod1 = " << prod << ", runtime1 = " << timer() << "ms" << std::endl;
timer.start();
prod=1;
for (int iter = 0; iter < 1000; iter++) {
for (auto it : data) {
prod = uint64_t(prod) * it % mod;
}
}
timer.finish();
std::cout << "prod2 = " << prod << ", runtime2 = " << timer() << "ms" << std::endl;
}
I3ByYWdtYSBHQ0Mgb3B0aW1pemUoIk9mYXN0IikKI2luY2x1ZGUgPGJpdHMvc3RkYysrLmg+CnN0YXRpYyB1bnNpZ25lZCBmYXN0X21vZCh1aW50NjRfdCB4LCB1bnNpZ25lZCBtKSB7CiAgICAvLyBPcHRpbWl6ZWQgbW9kIGZvciBDb2RlZm9yY2VzIDMyLWJpdCBtYWNoaW5lcy4KICAgIC8vIHggbXVzdCBiZSBsZXNzIHRoYW4gMl4zMiAqIG0gZm9yIHRoaXMgdG8gd29yaywgc28gdGhhdCB4IC8gbSBmaXRzIGluIGFuIHVuc2lnbmVkIDMyLWJpdCBpbnQuCiAgICB1bnNpZ25lZCB4X2hpZ2ggPSB1bnNpZ25lZCh4ID4+IDMyKSwgeF9sb3cgPSB1bnNpZ25lZCh4KTsKICAgIHVuc2lnbmVkIHF1b3QsIHJlbTsKICAgIGFzbSgiZGl2bCAlNFxuIgogICAgICAgIDogIj1hIiAocXVvdCksICI9ZCIgKHJlbSkKICAgICAgICA6ICJkIiAoeF9oaWdoKSwgImEiICh4X2xvdyksICJyIiAobSkpOwogICAgcmV0dXJuIHJlbTsKfQoKY2xhc3MgVGltZXIgewogICAgc3RkOjpjaHJvbm86OnRpbWVfcG9pbnQ8c3RkOjpjaHJvbm86OnN0ZWFkeV9jbG9jaz4gdGltZVBvaW50OwogICAgc2l6ZV90IHZhbHVlOwpwdWJsaWM6CiAgICB2b2lkIHN0YXJ0KCkgeyB0aW1lUG9pbnQgPSBzdGQ6OmNocm9ubzo6c3RlYWR5X2Nsb2NrOjpub3coKTsgfQogICAgdm9pZCBmaW5pc2goKSB7CiAgICAgICAgYXV0byBjdXJyID0gc3RkOjpjaHJvbm86OnN0ZWFkeV9jbG9jazo6bm93KCk7ICAgIAogICAgICAgIGF1dG8gZWxhcHNlZCA9IHN0ZDo6Y2hyb25vOjpkdXJhdGlvbl9jYXN0PHN0ZDo6Y2hyb25vOjptaWxsaXNlY29uZHM+KGN1cnIgLSB0aW1lUG9pbnQpOwogICAgICAgIHZhbHVlID0gZWxhcHNlZC5jb3VudCgpOwogICAgfQogICAgc2l6ZV90IG9wZXJhdG9yKCkoKSBjb25zdCB7IHJldHVybiB2YWx1ZTsgfQp9IHRpbWVyOwoKdWludDMyX3QgeDMyID0gMzE0MTU5MjY1Owp1aW50MzJfdCB4b3JzaGlmdDMyKCkKeyAvLyBmYXN0ZXN0IHJhbmRvbSBnZW5lcmF0b3IKICB4MzIgXj0geDMyIDw8IDEzOwogIHgzMiBePSB4MzIgPj4gMTc7CiAgeDMyIF49IHgzMiA8PCA1OwogIHJldHVybiB4MzI7Cn0KCmludCBtYWluKCkgewoJdW5zaWduZWQgbW9kOyBzdGQ6OmNpbiA+PiBtb2Q7CglzdGQ6OnZlY3Rvcjx1aW50MzJfdD4gZGF0YSgxIDw8IDE2KTsKCWZvciAoYXV0byYgaXQgOiBkYXRhKSBpdCA9IHhvcnNoaWZ0MzIoKTsKCXRpbWVyLnN0YXJ0KCk7Cgl1aW50MzJfdCBwcm9kPTE7Cglmb3IgKGludCBpdGVyID0gMDsgaXRlciA8IDEwMDA7IGl0ZXIrKykgewoJCWZvciAoYXV0byBpdCA6IGRhdGEpIHsKCQkJcHJvZCA9IGZhc3RfbW9kKHVpbnQ2NF90KHByb2QpKml0LG1vZCk7CgkJfQoJfQoJdGltZXIuZmluaXNoKCk7CglzdGQ6OmNvdXQgPDwgInByb2QxID0gIiA8PCBwcm9kIDw8ICIsIHJ1bnRpbWUxID0gIiA8PCB0aW1lcigpIDw8ICJtcyIgPDwgc3RkOjplbmRsOwoJdGltZXIuc3RhcnQoKTsKCXByb2Q9MTsKCWZvciAoaW50IGl0ZXIgPSAwOyBpdGVyIDwgMTAwMDsgaXRlcisrKSB7CgkJZm9yIChhdXRvIGl0IDogZGF0YSkgewoJCQlwcm9kID0gdWludDY0X3QocHJvZCkgKiBpdCAlIG1vZDsKCQl9Cgl9Cgl0aW1lci5maW5pc2goKTsKCXN0ZDo6Y291dCA8PCAicHJvZDIgPSAiIDw8IHByb2QgPDwgIiwgcnVudGltZTIgPSAiIDw8IHRpbWVyKCkgPDwgIm1zIiA8PCBzdGQ6OmVuZGw7Cn0=