Advertisement
dmkozyrev

idempotents

Mar 29th, 2015
251
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.39 KB | None | 0 0
  1. #include <iostream>
  2. #include <cmath>
  3. #include <vector>
  4. #include <stack>
  5. typedef long long i64;
  6. using namespace std;
  7.  
  8. bool diophant(i64 a, i64 b, i64 c, i64 &x, i64 &y);
  9. vector < i64 > idempotents(i64 n);
  10.  
  11. int main(){
  12.     i64 n;
  13.     cout << "Input N: ";
  14.     cin >> n;
  15.     vector <i64> answer = idempotents(n);
  16.     cout << "Count of idempotents = " << answer.size() << endl;
  17.     cout << "Idempotents: ";
  18.     for (auto i : answer) cout << i << " ";
  19. }
  20.  
  21. vector < i64 > idempotents(i64 n){
  22. //  Нахождение идемпотентов в кольце вычетов по модулю n
  23.     i64 m = n; // Запоминаем наше n
  24. //  Разбиваем n на взаимно простые множители и кидаем в вектор v. Считаем кол-во этих множителей
  25.     vector < i64 > v;
  26.     int c = 0;  
  27.     for (i64 i = 2; i <= n; ++i)
  28.         if (n % i == 0)
  29.         {
  30.             c++;
  31.             v.push_back(i);
  32.             n /= i;
  33.             while (n % i == 0)
  34.             {
  35.                 n /= i;
  36.                 v.back() *= i;
  37.             }
  38.         }
  39.     n = m; // Возвращаем n исходное значение
  40. //  Двоичный перебор всех представлений n = a * b , где НОД(a,b) = 1;
  41.     i64 limit = pow(2, c - 1), a, b, x, y;
  42.     vector < i64 > answer; // Будет хранить найденные идемпотенты
  43. //  Достаточно перебрать всего 2^(c-1) диофантовых уравнений, откуда мы вытащим один идемпотент
  44. //  И для найденного идемпотента х посчитаем 1-х парный идемпотент
  45.     for (i64 i = 1; i < limit; ++i)
  46.     {
  47.         m = i;
  48.         a = b = 1;
  49.         for (i64 j = 0; j < c; ++j)
  50.         {
  51.             if (m % 2 == 1)
  52.             {
  53.                 a *= v[j];
  54.             }
  55.             else
  56.             {
  57.                 b *= v[j];
  58.             }
  59.             m /= 2;
  60.         }
  61.         // Решаем полученное диофантово уравнение a*x + b*y = c
  62.         diophant(a, b, 1, x, y);
  63.         x *= a; // a*x - один идемпотент
  64.         // Приводим х к нормальному виду: 0 <= x < n
  65.         while (x < 0) x += n;
  66.         while (x >= n) x -= n;
  67.         // Находим парный к нему идемпотент
  68.         y = n + 1 - x;
  69.         // Кидаем оба идемпотента в вектор
  70.         answer.push_back(x);
  71.         answer.push_back(y);
  72.     }
  73. //  Ну и возвращаем вектор
  74.     return answer;
  75. }
  76.  
  77. bool diophant(i64 a, i64 b, i64 c, i64 &x, i64 &y){
  78.         stack < i64 >q;
  79.         i64 r;
  80.         while (a % b != 0)
  81.         {
  82.                 r = a % b;
  83.                 q.push(a / b);
  84.                 a = b;
  85.                 b = r;
  86.         }
  87.         if (b != 1)
  88.         {
  89.                 return false;
  90.         }
  91.         else
  92.         {
  93.                 i64 temp;
  94.                 x = 1;
  95.                 y = q.top();
  96.                 q.pop();
  97.                 while (!q.empty())
  98.                 {
  99.                         temp = x;
  100.                         x = -y;
  101.                         y = -temp - q.top() * y;
  102.                         q.pop();
  103.                 }
  104.                 x *= c;
  105.                 y *= -c;
  106.                 return true;
  107.         }
  108. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement