Tuesday, April 14, 2020

[Codeforces] E. Divisor Paths

Author            : Dipu Kumar Mohanto 
                    CSE, Batch - 6
                    BRUR.
Problem Statement : E. Divisor Paths
Source            : Codeforces 
Category          : Number Theory
Algorithm         : Pollard Rho Prime Factorization
Verdict           : Accepted

  1. #include "bits/stdc++.h"  
  2.   
  3. using namespace std;  
  4.   
  5. static const int maxn = 2e5 + 5;  
  6. static const long long mod = 998244353LL;  
  7.   
  8. namespace Rho  // Implementation: s_h_shahin, du
  9. {  
  10.       mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());  
  11.   
  12.       const int MAXP = 1000010;  
  13.       const int BASE[] = {2, 450775, 1795265022, 9780504, 28178, 9375, 325};  
  14.   
  15.       long long seq[MAXP];  
  16.       int primes[MAXP];  
  17.       int spf[MAXP];  
  18.   
  19.       inline long long mod_add(long long x, long long y, long long m)  
  20.       {  
  21.             x += y;  
  22.             if (x >= m) x -= m;  
  23.             return x;  
  24.       }  
  25.       inline long long mod_mul(long long x, long long y, long long m)  
  26.       {  
  27.             long long res = x * y - (long long)((long double)x * y / m + 0.5) * m;  
  28.             return res < 0 ? res + m : res;  
  29.       }  
  30.       inline long long mod_pow(long long x, long long p, long long m)  
  31.       {  
  32.             long long res = 1 % m;  
  33.             for ( ; p; p >>= 1)  
  34.             {  
  35.                   if (p & 1) res = mod_mul(res, x, m);  
  36.                   x = mod_mul(x, x, m);  
  37.             }  
  38.             return res;  
  39.       }  
  40.       // O(k * logn * logn * logn), k = number of rounds performed  
  41.       inline bool miller_robin(long long n)  
  42.       {  
  43.             if (n <= 2 or (~n & 1)) return (n == 2);  
  44.             if (n < MAXP) return spf[n] == n;  
  45.             long long c;  
  46.             long long d;  
  47.             long long s = 0;  
  48.             long long r = n - 1;  
  49.             while (~r & 1)  
  50.             {  
  51.                   s++;  
  52.                   r >>= 1;  
  53.             }  
  54.             // each iteration is a round  
  55.             for (int i = 0; primes[i] < n and primes[i] < 32; i++)  
  56.             {  
  57.                   c = mod_pow(primes[i], r, n);  
  58.                   for (int j = 0; j < s; j++)  
  59.                   {  
  60.                         d = mod_mul(c, c, n);  
  61.                         if (d == 1 and c != 1 and c != (n - 1)) return false;  
  62.                         c = d;  
  63.                   }  
  64.                   if (c != 1) return false;  
  65.             }  
  66.             return true;  
  67.       }  
  68.       inline void sieve()  
  69.       {  
  70.             int cnt = 0;  
  71.             for (int i = 2; i < MAXP; i++)  
  72.             {  
  73.                   if (spf[i] == 0) primes[cnt++] = spf[i] = i;  
  74.                   for (int j = 0; 1LL * i * primes[j] < MAXP; j++)  
  75.                   {  
  76.                         spf[i * primes[j]] = primes[j];  
  77.                         if (spf[i] == spf[i * primes[j]]) break;  
  78.                   }  
  79.             }  
  80.       }  
  81.       // expected complexity O(n ^ 1/4)  
  82.       long long pollard_rho(long long n)  
  83.       {  
  84.             while (true)  
  85.             {  
  86.                   long long x = rand() % n;  
  87.                   long long y = x;  
  88.                   long long c = rand() % n;  
  89.                   long long u = 1;  
  90.                   long long v;  
  91.                   long long t = 0;  
  92.                   long long *px = seq;  
  93.                   long long *py = seq;  
  94.                   while (true)  
  95.                   {  
  96.                         *py++ = y = mod_add(mod_mul(y, y, n), c, n);  
  97.                         *py++ = y = mod_add(mod_mul(y, y, n), c, n);  
  98.                         if ((x = *px++) == y) break;  
  99.                         v = u;  
  100.                         u = mod_mul(u, abs(y - x), n);  
  101.                         if (u == 0) return __gcd(v, n);  
  102.                         if (++t == 32)  
  103.                         {  
  104.                               t = 0;  
  105.                               if ((u = __gcd(u, n)) > 1 and u < n) return u;  
  106.                         }  
  107.                   }  
  108.                   if (t and (u = __gcd(u, n)) > 1 and u < n) return u;  
  109.             }  
  110.       }  
  111.       vector <long long> factorize(long long n)  
  112.       {  
  113.             if (n == 1) return vector <long long> ();  
  114.             if (miller_robin(n)) return vector <long long> {n};  
  115.             vector <long long> lchild, rchild;  
  116.             while (n > 1 and n < MAXP)  
  117.             {  
  118.                   lchild.push_back(spf[n]);  
  119.                   n /= spf[n];  
  120.             }  
  121.             if (n >= MAXP)  
  122.             {  
  123.                   long long x = pollard_rho(n);  
  124.                   lchild = factorize(x);  
  125.                   rchild = factorize(n / x);  
  126.                   lchild.insert(lchild.end(), rchild.begin(), rchild.end());  
  127.             }  
  128.             sort(lchild.begin(), lchild.end());  
  129.             return lchild;  
  130.       }  
  131. }  
  132.   
  133. long long binary_expo(long long a, long long p, long long m = mod)  
  134. {  
  135.       if (p == 0) return 1 % m;  
  136.       if (p == 1) return a % m;  
  137.       if (p & 1) return (a % m * binary_expo(a, p - 1, m)) % m;  
  138.       long long ret = binary_expo(a, p >> 1, m);  
  139.       return (ret % m * ret % m) % m;  
  140. }  
  141.   
  142. long long mod_inv(long long a, long long m = mod)  
  143. {  
  144.       return binary_expo(a, m - 2, m);  
  145. }  
  146.   
  147. long long fact[105];  
  148. long long ifact[105];  
  149.   
  150. void preCalc()  
  151. {  
  152.       fact[0] = 1;  
  153.       ifact[0] = 1;  
  154.       for (int i = 1; i < 105; i++)  
  155.       {  
  156.             fact[i] = (1LL * i * fact[i - 1]) % mod;  
  157.             ifact[i] = mod_inv(fact[i]);  
  158.       }  
  159. }  
  160.   
  161. vector <long long> factors;  
  162.   
  163. long long ways(long long n)  
  164. {  
  165.       int total = 0;  
  166.       long long ret = 1;  
  167.       for (long long pf : factors)  
  168.       {  
  169.             int cnt = 0;  
  170.             while (n % pf == 0) cnt++, n /= pf;  
  171.             ret = (ret * ifact[cnt]) % mod;  
  172.             total += cnt;  
  173.       }  
  174.       ret = (ret * fact[total]) % mod;  
  175.       return ret;  
  176. }  
  177.   
  178.   
  179. signed main()  
  180. {  
  181.       ios_base::sync_with_stdio(false);  
  182.       cin.tie(nullptr);  
  183.       cout.tie(nullptr);  
  184.   
  185.       #ifndef ONLINE_JUDGE  
  186.             freopen("in.txt""r", stdin);  
  187.       #endif // ONLINE_JUDGE  
  188.   
  189.       preCalc();  
  190.       Rho::sieve();  
  191.   
  192.       long long d;  
  193.       cin >> d;  
  194.       factors = Rho::factorize(d);  
  195.       sort(factors.begin(), factors.end());  
  196.       factors.erase(unique(factors.begin(), factors.end()), factors.end());  
  197.       int q;  
  198.       cin >> q;  
  199.       while (q--)  
  200.       {  
  201.             long long u, v;  
  202.             cin >> u >> v;  
  203.             long long g = __gcd(u, v);  
  204.             long long ans = (ways(u / g) * ways(v / g)) % mod;  
  205.             cout << ans << '\n';  
  206.       }  
  207. }  

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.