Advertisement
sarker306

Chinese Reminder for non co primes

Feb 3rd, 2016
123
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.32 KB | None | 0 0
  1. #include <bits/stdc++.h>
  2.  
  3. using namespace std;
  4. typedef long long ll;
  5.  
  6. #define SZ 1005001
  7. int phi[SZ];
  8. int factor[SZ];
  9. char isnp[SZ];
  10.  
  11. void initPhi(){
  12.     for ( int i = 0 ; i < SZ ; i++ ) phi[i] = factor[i] = i;
  13.     for ( int i = 4 ; i < SZ ; i += 2 ) isnp[i] = 1, factor[i] = 2;
  14.  
  15.     for ( int i = 9 ; i < SZ ; i += 3 ) isnp[i] = 1, factor[i] = 3;
  16.  
  17.     int nxt = 4;
  18.     for ( int i = 5 ; i * i < SZ ; ){
  19.         if ( isnp[i] == 0 ) {
  20.             for ( int j = i * i ; j < SZ ; j += i )
  21.                 isnp[j] = 1, factor[j] = i;
  22.         }
  23.  
  24.         nxt ^= 6;
  25.         i += nxt;
  26.     }
  27.  
  28.     cout << "done" << endl;
  29.     for ( int i = 2 ; i < SZ ; i++ ){
  30.         if ( isnp[i] == 0 ){
  31.             for ( int j = i ; j < SZ ; j += i ){
  32.                 phi[j] -= phi[j]/i;
  33.             }
  34.         }
  35.     }
  36.  
  37.     cout << "done" << endl;
  38. }
  39.  
  40. // ax + by = g
  41. // a'x' + b'y' = g , a'= b, b' = a - (a/b) * b
  42. // -> bx' + ay' - (a/b)*by' = g
  43. // -> ay' + b(x' - (a/b) * y') = g
  44. // -> x = y', y = x' - (a/b) * y'
  45. void extendedEuclid(int a, int b, int &x, int &y, int &g){
  46.     int x1, y1;
  47.  
  48.     if ( b == 0 ){
  49.         x = 1, y = 0, g = a;
  50.         return;
  51.     }
  52.  
  53.     int quo = a / b;
  54.     extendedEuclid(b, a - quo * b, x1, y1, g);
  55.     x = y1;
  56.     y = x1 - quo * y1;
  57. }
  58.  
  59. // ax = 1 mod b -> ax + by = 1
  60. // if x < 0, ab + ax = 1 mod b -> a(b + x) = 1 mod b
  61. int modInv(int a, int b){
  62.     int x, y, g;
  63.  
  64.     a %= b;
  65.     extendedEuclid(a, b, x, y, g);
  66.     if ( x < 0 ) x = b + x;
  67.  
  68.     //cout << "ModInv(" << a << "," << b <<") : " << x << endl;
  69.     return x;
  70. }
  71.  
  72. ll multMod(ll a, ll b, ll m){
  73.     ll res = 0;
  74.  
  75.     while ( b ){
  76.         if ( b & 1 ) res = ( res + a );
  77.         if ( res >= m ) res -= m;
  78.         a <<= 1;
  79.         if ( a >= m ) a -= m;
  80.         b >>= 1;
  81.     }
  82.  
  83.     return res;
  84. }
  85.  
  86. ll ChineseRemainder(vector<int> &residue, vector<int> &mods){
  87.     ll M = 1;
  88.     ll res = 0;
  89.  
  90.     for ( int i = 0 ; i < mods.size() ; i++ ){
  91.         M *= mods[i];
  92.     }
  93.    
  94.     for ( int i = 0 ; i < residue.size() ; i++ ){
  95.         ll temp = residue[i] * modInv(M / mods[i], mods[i]);
  96.         temp = multMod(temp, M / mods[i], M);
  97.         res = res + temp;
  98.         if ( res >= M ) res -= M;
  99.     }
  100.  
  101.     return res;
  102. }
  103.  
  104. map<int, int> factors[5001];
  105. // n is assumed to be between 1000000 and 1005000
  106. map<int, int> getFactors(int n){
  107.     int offset = 1000000;
  108.     if ( factors[n - offset].size() == 0 ){
  109.         int index = n - offset;
  110.         int m = n;
  111.         while ( m > 1 ) {
  112.             int v = 0;
  113.             int f = factor[m];
  114.             while ( m % f == 0 ) v++, m /= f;
  115.             factors[index].insert(pair<int, int>(f, v));
  116.         }
  117.     }
  118.    
  119.     return factors[n - offset];
  120. }
  121.  
  122. //int powers[10005000][20];
  123. int findPower(int b, int p) {
  124.     int res = 1, tmp = b;
  125.  
  126.     while (p){
  127.         if (p & 1) res = res * tmp;
  128.         tmp *= tmp;
  129.         p >>= 1;
  130.     }
  131.  
  132.     return res;
  133. }
  134.  
  135. long long chineseNonCoPrime(int n, int modn, int m, int modm) {
  136.     map<int, int>::iterator ptrMap, ptrMap1;
  137.     vector<int> res;
  138.     vector<int> mods;
  139.     map<int, int> fn = getFactors(n);
  140.     map<int, int> fm = getFactors(m);
  141.  
  142.     for ( ptrMap = fn.begin(), ptrMap1 = fm.begin() ; ptrMap != fn.end() && ptrMap1 != fm.end() ; ) {
  143.         if ( ptrMap->first == ptrMap1->first ){
  144.             int p1 = findPower(ptrMap->first, ptrMap->second);
  145.             int p2 = findPower(ptrMap1->first, ptrMap1->second);
  146.             int m1 = modn % p1;
  147.             int m2 = modm % p2;
  148.  
  149.             //printf("case 1 -> (%d mod %d), (%d mod %d)\n", m1, p1, m2, p2);
  150.             int diff = ptrMap->second - ptrMap1->second;
  151.  
  152.             if ( diff == 0 && m1 != m2 ) return 0;
  153.  
  154.             if ( diff < 0 ){
  155.                 diff = -diff;
  156.                 if ( m2 != m1 ) m2 ^= m1 ^= m2 ^= m1;
  157.                 if ( p2 != p1 ) p2 ^= p1 ^= p2 ^= p1;
  158.             }
  159.  
  160.             //printf("Now, case 1 -> (%d mod %d), (%d mod %d).... diff %d\n", m1, p1, m2, p2, p1/p2);
  161.             if (m1 >= m2 && ((m1 - m2) % (p1/p2) == 0)) {
  162.                 res.push_back(m1);
  163.                 mods.push_back(p1);
  164.             } else return 0;
  165.  
  166.             ptrMap++, ptrMap1++;
  167.         } else if ( ptrMap->first < ptrMap1->first ) {
  168.             int p1 = findPower(ptrMap->first, ptrMap->second);
  169.  
  170.             res.push_back(modn % p1);
  171.             mods.push_back(p1);
  172.  
  173.             ptrMap++;
  174.         } else {
  175.             int p2 = findPower(ptrMap1->first, ptrMap1->second);
  176.  
  177.             res.push_back(modm % p2);
  178.             mods.push_back(p2);
  179.  
  180.             ptrMap1++;
  181.         }
  182.     }
  183.  
  184.     while ( ptrMap != fn.end()) {
  185.         int p1 = findPower(ptrMap->first, ptrMap->second);
  186.  
  187.         res.push_back(modn % p1);
  188.         mods.push_back(p1);
  189.  
  190.         ptrMap++;
  191.     }
  192.  
  193.     while ( ptrMap1 != fm.end() ){
  194.         int p2 = findPower(ptrMap1->first, ptrMap1->second);
  195.  
  196.         res.push_back(modm % p2);
  197.         mods.push_back(p2);
  198.  
  199.         ptrMap1++;
  200.     }
  201.  
  202.     //printf("Found all res and mods, now going to remainder\n");
  203.     return ChineseRemainder(res, mods);
  204. }
  205.  
  206. int main(){
  207.     int n, m, a, b;
  208.     map<int, int>::iterator ptrMap;
  209.  
  210.     initPhi();
  211.  
  212.  
  213.     // n is assumed to be between 1000000 and 1005000
  214.     /*while ( cin >> n ){
  215.         map<int, int> f = getFactors(n);
  216.         for ( ptrMap = f.begin() ; ptrMap != f.end() ; ptrMap++ )
  217.             cout << ptrMap->first << "^" << ptrMap->second << " ";
  218.         cout << endl;
  219.     }*/
  220.  
  221.     /*while ( cin >> a >> n >> b >> m ){
  222.     //while ( cin >> n >> m ){
  223.         cout << chineseNonCoPrime(n,a,m,b) << endl;
  224.     }*/
  225.     long long res = 0;
  226.     for ( int n = 1000000 ; n < 1005000 ; n++ ){
  227.         for ( int m = n + 1 ; m < 1005000 ; m++ )
  228.             res += chineseNonCoPrime(n, phi[n], m, phi[m]);
  229.         cout << n << " ended" << endl;
  230.     }
  231.     cout << res << endl;
  232.     getchar();
  233.  
  234.     return 0;
  235. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement