joylintp

solve.cpp

Jan 24th, 2021
207
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.69 KB | None | 0 0
  1. #include <bits/extc++.h>
  2.  
  3. using namespace std;
  4. using ll = long long;
  5.  
  6. using LLL = __int128;
  7.  
  8. ll modpow(ll e, ll p, ll m) {
  9.     ll r = 1;
  10.     while(p) {
  11.         if(p & 1) r = (LLL)r * e % m;
  12.         e = (LLL) e * e % m;
  13.         p >>= 1;
  14.     }
  15.     return r;
  16. }
  17.  
  18. ll modmul(ll a, ll b, ll m) {
  19.     return (LLL) a * b % m;
  20. }
  21.  
  22. struct Factorization {
  23.     struct MillerRabin {
  24.         // n < 4759123141     chk = [2, 7, 61]
  25.         // n < 1122004669633  chk = [2, 13, 23, 1662803]
  26.         // n < 2^64           chk = [2, 325, 9375, 28178, 450775, 9780504, 1795265022]
  27.         vector<long long> chk = {2,325,9375,28178,450775,9780504,1795265022};
  28.         bool Check(long long a, long long u, long long n, int t) {
  29.             a = modpow(a, u, n);
  30.             if (a == 0 || a == 1 || a == n - 1) return true;
  31.             for (int i = 0; i < t; ++i) {
  32.                 a = modmul(a, a, n);
  33.                 if (a == 1) return false;
  34.                 if (a == n - 1) return true;
  35.             }
  36.             return false;
  37.         }
  38.         bool operator()(long long n) {
  39.             if (n < 2) return false;
  40.             if (n % 2 == 0) return n == 2;
  41.             long long u = n - 1; int t = 0;
  42.             for (; !(u & 1); u >>= 1, ++t);
  43.             for (long long i : chk) {
  44.                 if (!Check(i, u, n, t)) return false;
  45.             }
  46.             return true;
  47.         }
  48.     } prime;
  49.     map<long long, int> cnt;
  50.     void pollardRho(long long n) {
  51.         if (n == 1) return;
  52.         if (prime(n)) return ++cnt[n], void();        
  53.         if (n % 2 == 0) return pollardRho(n / 2), ++cnt[2], void();
  54.         long long x = 2, y = 2, d = 1, p = 1;
  55.         auto f = [&](auto x, auto n, int p) { return (modmul(x, x, n) + p) % n; };
  56.         while (true) {
  57.             if (d != n && d != 1) {
  58.                 pollardRho(n / d);
  59.                 pollardRho(d);
  60.                 return;
  61.             }
  62.             if (d == n) ++p;
  63.             x = f(x, n, p); y = f(f(y, n, p), n, p);
  64.             d = __gcd(abs(x - y), n);
  65.         }
  66.     }
  67.     ll mxPrime(ll n) {
  68.         ll mx = 0;
  69.         cnt.clear();
  70.         pollardRho(n);
  71.         for(auto [a, b]: cnt) mx = max(mx, a);
  72.         return mx;
  73.     }
  74. } factor;
  75.  
  76.  
  77. struct CRT {
  78.     ll R, M;
  79.     CRT() : R(0), M(1) {}
  80.     template <typename T> tuple<T, T, T> extgcd(T a, T b) {
  81.         if (!b) return make_tuple(a, 1, 0);
  82.         T d, x, y;
  83.         tie(d, x, y) = extgcd(b, a % b);
  84.         return make_tuple(d, y, x - (a / b) * y);
  85.     }
  86.     void add(ll r, ll m) {
  87.         long long d, x, y;
  88.         tie(d, x, y) = extgcd(M, m * 1ll);
  89.         assert ((r - R) % d == 0);
  90.         long long new_M = M / __gcd(M, 1ll * m) * m;
  91.         R += modmul(modmul(x, (r - R) / d, new_M), M, new_M);
  92.         M = new_M;
  93.         ((R %= M) += M) %= M;
  94.     }
  95.     pair<ll,ll> operator()() const {
  96.         return {R, M};
  97.     }
  98. };
  99.  
  100. ll BSGS(ll a, ll b, ll m, ll T) {
  101.     // a^x = b (mod m), and T is the period
  102.     ll n = sqrt(T) + 1;
  103.  
  104.     ll an = modpow(a, n, m);
  105.  
  106.     unordered_map<ll, ll> vals;
  107.     for (ll q = 0, cur = b; q <= n; ++q) {
  108.         vals[cur] = q;
  109.         cur = ((LLL) cur * a) % m;
  110.     }
  111.     // std::cerr << "q = " << q << '\n';
  112.  
  113.     for (ll p = 1, cur = 1; p <= n; ++p) {
  114.         cur = ((LLL) cur * an) % m;
  115.         if (vals.count(cur)) {
  116.             ll ans = n * p - vals[cur];
  117.             return ans;
  118.         }
  119.     }
  120.     cerr << "a = " << a << " b = " << b << " m = " << m << " T = " << T << '\n';
  121.     cerr << "NOT FOUND\n";
  122.     exit(1);
  123. }
  124.  
  125. using __gnu_cxx::power;
  126.  
  127. ll discreteLog(ll a, ll b, ll m) {
  128.     // m is prime
  129.     auto solve = [m](ll g, ll h, ll p, ll e) {
  130.         ll x = 0;
  131.         ll r = modpow(g, power(p, e-1), m);
  132.         ll invg = modpow(g, m-2, m);
  133.         for(int k = 0; k < e; k++) {
  134.             ll hk = modpow(modmul(modpow(invg, x, m), h, m), power(p, e-1-k), m);
  135.             ll d = BSGS(r, hk, m, p);
  136.             x += power(p, k) * d;
  137.             // cerr<<"k = "<<k<<" ; ";
  138.         }
  139.         // cerr << '\n';
  140.         return x;
  141.     };
  142.     ll phi = m-1;
  143.     CRT crt;
  144.     for(auto [p, e]: factor.cnt) {
  145.         ll P = power(p, e);
  146.         ll X = solve(modpow(a, phi / P, m), modpow(b, phi / P, m), p, e);
  147.         crt.add(X, P);
  148.     }
  149.     assert(crt().second == phi);
  150.     assert(modpow(a, crt().first, m) == b);
  151.     return crt().first;
  152. }
  153.  
  154.  
  155. struct Edge {
  156.     int j;
  157.     ll m, g, A, B;
  158.     Edge(int j, ll m, ll g, ll A, ll B) : j(j), m(m), g(g), A(A), B(B) {}
  159. };
  160.  
  161. signed main() {
  162.     std::cerr << "solve.cpp::main() start.\n";
  163.     ios_base::sync_with_stdio(0), cin.tie(0);
  164.     const int n = 420;
  165.     int a, b;
  166.     vector<vector<Edge>> adj(n);
  167.     while(cin >> a >> b) {
  168.         assert(1 <= a && a <= n && 1 <= b && b <= n && a != b);
  169.         ll m, g, A, B;
  170.         cin >> m >> g >> A >> B;
  171.         --a, --b;
  172.         adj[a].emplace_back(b, m, g, A, B);
  173.         adj[b].emplace_back(a, m, g, B, A);
  174.     }
  175.     vector<ll> ans;
  176.     vector<int> vis(n);
  177.     function<void(int)> dfs = [&](int i) {
  178.         vis[i] = true;
  179.         for(auto [j, m, g, A, B]: adj[i]) {
  180.             if(vis[j]) continue;
  181.             if(factor.mxPrime(m-1) >= 1e15) {
  182.                 cerr << m-1 << '\n';
  183.                 continue;
  184.             }
  185.             // cerr << A << ' ' << B << '\n';
  186.             ll sa = discreteLog(g, A, m);
  187.             ll sb = discreteLog(g, B, m);
  188.             assert(modpow(g, sa, m) == A && modpow(g, sb, m) == B);
  189.             ans.emplace_back(modpow(A, sb, m));
  190.             // cerr << ans.back() << '\n';
  191.             dfs(j);
  192.         }
  193.     };
  194.     dfs(0);
  195.     std::cerr << "ans.size() = " << ans.size() << '\n';
  196.     assert(ans.size() == n-1);
  197.     for(ll x: ans)
  198.         cout << x << '\n';
  199. }
  200.  
  201.  
Advertisement
Add Comment
Please, Sign In to add comment