#include<bits/stdc++.h> #define cerr(x) std::cerr << (#x) << " is " << (x) << '\n' using LL = longlong;
intpowMod(int x, int n, int M){ int r = 1; while (n) { if (n&1) r = 1LL * r * x % M; n >>= 1; x = 1LL * x * x % M; } return r; }
template<typename T> std::tuple<T, T, T> exGcd(T a, T b){ if (b == 0) return {a, 1, 0}; auto [d, y, x] = exGcd(b, a % b); return {d, x, y - a / b * x}; }
voidgenerate(int m){ if ((m & -m) == m) { std::clog << "You may use bit operators instead:\n\n"; std::cout << "unsigned fastPowMod" << m << "(unsigned x, unsigned n) {\n"; std::cout << " unsigned r = 1;\n"; std::cout << " while (n) {\n"; std::cout << " if (n & 1) r = 1LL * r * x &" << m - 1 << "U;\n"; std::cout << " n >>= 1; r = 1LL * x * x &" << m - 1 << "U;\n"; std::cout << " }\n"; std::cout << " return r;\n"; std::cout << "}\n\n"; return; } elseif (m % 2 == 0) { std::cerr << "Sorry, not support for even number which is not power of 2: " << m << "\n\n"; return; } elseif (m >> 30) { std::cerr << "Sorry, not support for number bigger than 2^30: " << m << "\n\n"; return; } auto [d, x, y] = exGcd(1LL << 32, 1LL * m); y = -y; if (y < 0) y += 1LL << 32; int m1 = (1LL << 32) % m; auto [d1, x1, y1] = exGcd(m1, m); if (x1 < 0) x1 += m; std::cout << "using ULL = unsigned long long;\n"; std::cout << "unsigned fastPowMod" << m << "(unsigned x, unsigned n) {\n"; std::cout << " static const unsigned m = " << m << "U;\n"; std::cout << " static const unsigned mr = " << y << "U;\n"; std::cout << " static const unsigned m1 = " << m1 << "U;\n"; std::cout << " static const unsigned m1inv = " << x1 << "U;\n"; std::cout << " unsigned xx = (ULL(x) << 32) % m, rr = m1;\n"; std::cout << " while (n) {\n"; std::cout << " if (n & 1) {\n"; std::cout << " ULL t = ULL(rr) * xx;\n"; std::cout << " rr = (t + ULL(unsigned(t) * mr) * m) >> 32;\n"; std::cout << " }\n"; std::cout << " ULL t = ULL(xx) * xx;\n"; std::cout << " xx = (t + ULL(unsigned(t) * mr) * m) >> 32;\n"; std::cout << " n >>= 1;\n"; std::cout << " }\n"; std::cout << " return ULL(rr) * m1inv % m;\n"; std::cout << "}\n\n"; }
intmain(){ constint N = 3e7; std::vector<int> a(N); for (int i = 0; i < N; ++i) a[i] = rnd() % M; { Timer A("fast?"); LL sum = 0; for (int i = 0; i < N; ++i) { sum += fastPowMod998244353(a[i], i); } cerr(sum); } { Timer A("default"); LL sum = 0; for (int i = 0; i < N; ++i) { sum += powMod(a[i], i); } cerr(sum); } return0; }
intmain(){ constint N = 1e7 + 2; // test for mod = 14 { std::vector<uint32_t> a(N); for (auto &x : a) x = rnd(); constuint32_t modConst = 14; uint32_t mod = 14; for (auto x : a) { if (div14(x) != x / mod) { std::cerr << x << ' ' << div14(x) << ' ' << x / mod << '\n'; return-1; } } { Timer A("mod14"); uint64_t sum = 0; for (auto x : a) sum += div14(x); cerr(sum); } { Timer A("default"); uint64_t sum = 0; for (auto x : a) sum += x / mod; cerr(sum); } { Timer A("const default"); uint64_t sum = 0; for (auto x : a) sum += x / modConst; cerr(sum); } } NewLine; // test for uint32 { std::vector<uint32_t> a(N); for (auto &x : a) x = rnd(); uint32_t mod = 0; while ((mod = rnd()) == 0); auto f = getDivFun<uint32_t, u_int64_t>(mod); for (auto x : a) { if (f(x) != x / mod) { std::cerr << x << ' ' << f(x) << ' ' << x / mod << '\n'; return-1; } } { Timer A("default"); uint64_t sum = 0; for (auto x : a) sum += x / mod; cerr(sum); } { Timer A("fast?"); uint64_t sum = 0; for (auto x : a) sum += f(x); cerr(sum); } } NewLine; // test for uint64 { std::vector<uint64_t> a(N); for (auto &x : a) x = rnd(); uint64_t mod = 0; while ((mod = rnd64()) == 0); mod = mod % INT_MAX; // avoid answer too small auto f = getDivFun<u_int64_t, __uint128_t>(mod); for (auto x : a) { if (f(x) != x / mod) { std::cerr << x << ' ' << f(x) << ' ' << x / mod << '\n'; return-1; } } { Timer A("default"); __uint128_t sum = 0; for (auto x : a) sum += x / mod; cerr(uint64_t(sum >> 64)); cerr(uint64_t(sum)); } { Timer A("fast?"); __uint128_t sum = 0; for (auto x : a) sum += f(x); cerr(uint64_t(sum >> 64)); cerr(uint64_t(sum)); } } }