Advertisement
dmkozyrev

equation

Apr 1st, 2015
299
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 7.10 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. bool increment(vector<i64>&pair, vector<vector<i64>>&v);
  8. vector<i64> perebor(vector<vector<i64>>& v, vector<i64>& p, vector<i64>& idempotents);
  9. vector<i64>decomposition(i64 n);
  10. vector<i64>find_x(vector<i64>& v, i64 n);
  11. i64 calc_value(vector<i64>& v, i64 x, i64 n);
  12. bool diophant(i64 a, i64 b, i64 c, i64 &x, i64 &y);
  13. vector < i64 > idempotents_from_vector(vector <i64> & v);
  14. vector<i64> find_idempotents(vector<i64> &idempotents, vector<i64> &v_z);
  15. i64 calc_number(vector<i64>&idempotents, vector<i64>& v_z, vector<i64>& v_ost);
  16.  
  17. int main(){
  18.     i64 a,m,n; vector <i64> v;
  19.     cout<<"Input degree of polynom(m) and base of Zn: ";
  20.     cin>>m>>n;
  21.     cout<<"Input a[0], a[1], ..., a[m] from polynom a[0]*x^m+a[1]*x^(m-1)+...+a[m] = 0: ";
  22.     for (i64 i=0; i<=m; ++i){
  23.         cin>>a;
  24.         v.push_back(a);
  25.     }
  26.     cout<<endl<<"SOLUTION: "<<endl;
  27.     vector<i64> p = decomposition(n);
  28.     vector<i64> mas = idempotents_from_vector(p);
  29.     vector<i64> idempotents = find_idempotents(mas, p);
  30.     vector<vector<i64>> x;
  31.     for (auto &i:p){
  32.         x.push_back(find_x(v,i));
  33.         cout<<"for p = "<<i<<": ";
  34.         for(auto &j : x.back())cout<<j<<" ";
  35.         cout<<endl;
  36.     }
  37.     cout << "ALLRIGHT" << endl;
  38.     vector<i64> answer= perebor(x, p, idempotents);
  39.     cout<<"ANSWER: ";
  40.     for(auto &i : answer) cout<<i<<" ";
  41.     cout<<endl<<"CHECK THIS: "<<endl;
  42.     for(auto &x : answer)
  43.     cout<<"for x="<<x<<": polynom(x) = "<< calc_value(v, x, n)<<endl;
  44. }
  45.  
  46.  
  47. bool increment(vector<i64>&pair, vector<vector<i64>>&v){
  48.     for (i64 i = 0; i< v.size(); ++i){
  49.         pair[i]++;
  50.         if (pair[i] == v[i].size()) pair[i]=0; else  return true;
  51.     }
  52.     return false;
  53. }
  54.  
  55. vector<i64> perebor(vector<vector<i64>>& v, vector<i64>& p, vector<i64>& idempotents){
  56.     vector<i64>pair, w, answer;
  57.     for(i64 i=0; i<v.size(); ++i){ pair.push_back(0); w.push_back(0);}
  58.     bool flag;
  59.     do {
  60.         for (i64 i=0; i<v.size(); ++i) w[i]=v[i][pair[i]];
  61.         answer.push_back(calc_number(idempotents, p, w));
  62.         flag = increment(pair, v);
  63.     } while (flag);
  64.     return answer;
  65. }
  66.  
  67. vector<i64>decomposition(i64 n){
  68.     vector<i64>v;
  69.     for (i64 i = 2; i <= n; ++i)
  70.         if (n % i == 0)
  71.         {
  72.             v.push_back(i);
  73.             n /= i;
  74.             while (n % i == 0)
  75.             {
  76.                 n /= i;
  77.                 v.back() *= i;
  78.             }
  79.         }
  80.   return v;
  81. }
  82.  
  83. vector<i64>find_x(vector<i64>& v, i64 n){
  84.     vector<i64>x;
  85.     for (i64 i=0; i<n; ++i){
  86.         i64 y = calc_value(v, i, n);
  87.         if (y==0)x.push_back(i);
  88.     }
  89.     return x;
  90. }
  91.  
  92. i64 calc_value(vector<i64>& v, i64 x, i64 n){
  93.     i64 b=0;
  94.     for(auto &a : v){
  95.         b = x*b + a;
  96.         while (b>=n) b-=n;
  97.         while (b<0) b+=n;
  98.     }
  99.     return b;
  100. }
  101.  
  102. bool diophant(i64 a, i64 b, i64 c, i64 &x, i64 &y){
  103. //  Решение диофантового уравнения a*x + b*y = c методом Евклида
  104.     stack < i64 >q;
  105.     i64 r;
  106.     while (a % b != 0)
  107.     {
  108.         r = a % b;
  109.         q.push(a / b);
  110.         a = b;
  111.         b = r;
  112.     }
  113.     if (b != 1)
  114.     {
  115.         return false;
  116.     }
  117.     else
  118.     {
  119.         i64 temp;
  120.         x = 1;
  121.         y = q.top();
  122.         q.pop();
  123.         while (!q.empty())
  124.         {
  125.             temp = x;
  126.             x = -y;
  127.             y = -temp - q.top() * y;
  128.             q.pop();
  129.         }
  130.         x *= c;
  131.         y *= -c;
  132.         return true;
  133.     }
  134. }
  135.  
  136. vector < i64 > idempotents_from_vector(vector <i64> & v){
  137. //  Нахождение идемпотентов в кольце вычетов по модулю n, где n - произведение всех элементов вектора v, состоящего из взаимно простых чисел
  138.     i64 n = 1, m;
  139. //  Вычисление n
  140.     for (auto &i : v) n *= i;
  141. //  Двоичный перебор всех представлений n = a * b , где НОД(a,b) = 1;    
  142.     int c = v.size();
  143.     i64 limit = pow(2, c - 1), a, b, x, y;
  144.     vector < i64 > answer; // Будет хранить найденные идемпотенты
  145. //  Достаточно перебрать всего 2^(c-1) диофантовых уравнений, откуда мы вытащим один идемпотент
  146. //  И для найденного идемпотента х посчитаем 1-х парный идемпотент
  147.     for (i64 i = 1; i < limit; ++i)
  148.     {
  149.         m = i;
  150.         a = b = 1;
  151.         for (i64 j = 0; j < c; ++j)
  152.         {
  153.             if (m % 2 == 1)
  154.                 a *= v[j];
  155.             else
  156.                 b *= v[j];
  157.             m /= 2;
  158.         }
  159.         // Решаем полученное диофантово уравнение a*x + b*y = c
  160.         diophant(a, b, 1, x, y);
  161.         // a*x - один идемпотент
  162.         x *= a;
  163.         // Приводим х к нормальному виду: 0 <= x < n
  164.         while (x < 0) x += n;
  165.         while (x >= n) x -= n;
  166.         // Находим парный к нему идемпотент
  167.         y = n + 1 - x;
  168.         // Кидаем оба идемпотента в вектор
  169.         answer.push_back(x);
  170.         answer.push_back(y);
  171.     }
  172. //  Ну и возвращаем вектор
  173.     return answer;
  174. }
  175.  
  176. vector<i64> find_idempotents(vector<i64> &idempotents, vector<i64> &v_z){
  177. //  Вектор idempotents хранит все идемпотенты кольца вычетов с основанием n
  178. //  Вектор v_z хранит все основания колец вычетов , введенные пользователем
  179. //  Вектор v_ost хранит все остатки от сравнения по модулю с соответсвующим основанием кольца вычетов
  180.     i64 n = 1 ;
  181. //  Так как мы не передаём n , то посчитаем его как произведение всех элементов вектора v_z 
  182.     vector<i64> answer;
  183.     for (auto &i : v_z) { n *= i; answer.push_back(0);}
  184. //  Затем сопоставим каждому j-ому кольцу вычетов v_z[j] i-ый идемпотент кольца вычетов по модулю n 
  185.     for (auto &a : idempotents){
  186.         int t = -1, k = 0;
  187.         bool flag = true;
  188.         for(auto &b : v_z){
  189.             // Ищем единственную возможную единицу в остатке при делении a[i] на b[j] .
  190.             // Все остальные остатки при делении a[i] на b[k], где k != j, должны быть нулями
  191.             if (a % b == 1)
  192.                 if (t != -1){
  193.                     flag = false;
  194.                     break;
  195.                 } else
  196.                     t = k;
  197.             ++k;
  198.         }
  199.         // Если мы нашли соответсвующий идемпотент для v_z[t], то сразу умножаем его на v_ost[t] и прибавляем к искомому числу
  200.         if ( flag )
  201.             answer[t] = a;
  202.     }
  203. // Возвращаем искомое число
  204.     return answer; 
  205. }
  206.  
  207.  
  208. i64 calc_number(vector<i64>&idempotents, vector<i64>& v_z, vector<i64>& v_ost){
  209.     i64 n=1, num =0;
  210.     for (auto &i : v_z) n *= i;
  211.     for (int i=0; i<v_z.size(); ++i){
  212.         num += idempotents[i]*v_ost[i];
  213.         if (num>=n) num%=n;
  214.     }
  215.     return num;
  216. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement