Advertisement
hpnq

лаба 11

May 6th, 2024
557
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 10.86 KB | Source Code | 0 0
  1. #include "bits/stdc++.h"
  2. //speed coding handle
  3.  
  4. #define mp make_pair
  5. #define cve(tpy) for (auto i : tpy) {for(auto j : i){cout << j << " ";  }cout << "\n";} ;
  6. #define f first
  7. #define s second
  8. #define loop(i, x, n) for (int i = x; i < n; i++)
  9. #define joop(x, n) for (ll j = x; j < n; j++)
  10. #define lp(n) for (ll i = 0; i < n; i++)
  11. #define err cout << "ERROR" << endl;
  12. #define all(x) x.begin(), x.end()
  13. #define pb push_back
  14. #define sz(x) x.size()
  15. #define rndm rng()
  16.  
  17. // types
  18. #define pii pair<int, int>
  19. #define pll pair<ll, ll>
  20. #define vvi vector<vector<int>>
  21. #define vvll vector<vector<ll>>
  22. typedef long long ll;
  23. typedef long double ld;
  24.  
  25. // types of data
  26. #define inf 1000000000
  27. #define infll 1000000000000000000
  28. #define INF ll(1e18)
  29.  
  30. #define md 998244353
  31. #define mod 1000000009
  32. //#define K 239017
  33.  
  34. #define DEBUG 1
  35. using namespace std;
  36. mt19937_64 rng(113113);
  37. uniform_int_distribution<ll> drist;
  38.  
  39. // code
  40.  
  41.  
  42. struct bignumber // описание узла
  43. {
  44.     short digit; // цифра
  45.     bignumber* next; // поле для связи со следующей цифрой числа
  46. };
  47. bignumber* create(string str) // создание большого числа из текстовой строки
  48. {
  49.     bignumber* p, * top = nullptr;
  50.     int i;
  51.     for (i = 0; i < str.size() ; i++)
  52.     {
  53.         p = new bignumber;
  54.         p->digit = short(str[i]) - short('0');
  55.         p->next = top;
  56.         top = p;
  57.     }
  58.     return top;
  59. }
  60. void print(const bignumber* BigNum) // рекурсивная распечатка цифр числа
  61. {
  62.     if (BigNum != nullptr) // если ещё не конец числа
  63.     {
  64.         print(BigNum->next); //вызываем печать для старшего разряда
  65.         cout << BigNum->digit; //печать текущего разряда
  66.     }
  67. }
  68. void clear(bignumber** BigNum) // очистка стека (удаление всех узлов из стека)
  69. {
  70.     bignumber* temp;
  71.     while (*BigNum != nullptr) // пока не достигли конца
  72.     {
  73.         temp = (*BigNum)->next; // устанавливаем указатель temp на следующий элемент
  74.         delete* BigNum;
  75.         *BigNum = temp; // переводим указатель на следующий элемент
  76.     }
  77. }
  78.  
  79. int dlina(bignumber* BigNum)
  80. {
  81.     int k = 0;
  82.     while (BigNum != nullptr)
  83.     {
  84.         k++;
  85.         BigNum = BigNum->next;
  86.     }
  87.     return k;
  88. }
  89.  
  90.  
  91. bool Eq(bignumber* BigNum1, bignumber* BigNum2) //проверка, что BigNum1=BigNum2
  92. {
  93.     if (dlina(BigNum1) != dlina(BigNum2)) return false;
  94.     else //если одинаковое число разрядов
  95.     {
  96.         bool fl = true;
  97.         while (BigNum1 != nullptr)//проверяем совпадение цифр
  98.         {
  99.             if (BigNum1->digit != BigNum2->digit) { fl = false; break; }
  100.             BigNum1 = BigNum1->next;
  101.             BigNum2 = BigNum2->next;
  102.         }
  103.         return fl;
  104.     }
  105. }
  106. int sravn(bignumber* BigNum1, bignumber* BigNum2)
  107. {//если равное число разрядов, сравниваем цифры
  108.     if (BigNum1 == nullptr) return 0;
  109.     else
  110.     {
  111.         int k = sravn(BigNum1->next, BigNum2->next);
  112.         if (k != 0) return k;
  113.         else //k=0, старшие разряды были одинаковые
  114.             return BigNum1->digit - BigNum2->digit;
  115.     }
  116. }
  117.  
  118.  
  119. bool More(bignumber* BigNum1, bignumber* BigNum2) //BigNum1>BigNum2
  120. {
  121.     int d1 = dlina(BigNum1), d2 = dlina(BigNum2);
  122.     if (d1 < d2) return false;
  123.     if (d1 > d2) return true;
  124.     //если одинаковое число разрядов
  125.     int k = sravn(BigNum1, BigNum2);
  126.     if (k > 0) return true;
  127.     return false;
  128. }
  129.  
  130. bool Less(bignumber* BigNum1, bignumber* BigNum2) //BigNum1<BigNum2
  131. {
  132.     int d1 = dlina(BigNum1), d2 = dlina(BigNum2);
  133.     if (d1 < d2) return true;
  134.     if (d1 > d2) return false;
  135.     //если одинаковое число разрядов
  136.     int k = sravn(BigNum1, BigNum2);
  137.     if (k < 0) return true;
  138.     return false;
  139. }
  140.  
  141. bool LessEq(bignumber* BigNum1, bignumber* BigNum2) //BigNum1<=BigNum2
  142. {
  143.     int d1 = dlina(BigNum1), d2 = dlina(BigNum2);
  144.     if (d1 < d2) return true;
  145.     if (d1 > d2) return false;
  146.     //если одинаковое число разрядов
  147.     int k = sravn(BigNum1, BigNum2);
  148.     if (k <= 0) return true;
  149.     return false;
  150. }
  151. bool MoreEq(bignumber* BigNum1, bignumber* BigNum2) //BigNum1>BigNum2
  152. {
  153.     int d1 = dlina(BigNum1), d2 = dlina(BigNum2);
  154.     if (d1 < d2) return false;
  155.     if (d1 > d2) return true;
  156.     //если одинаковое число разрядов
  157.     int k = sravn(BigNum1, BigNum2);
  158.     if (k >= 0) return true;
  159.     return false;
  160. }
  161.  
  162. void addto(bignumber** BigNum1, bignumber* BigNum2)
  163. {//сложение двух больших чисел с накапливанием в первое
  164.     if (!BigNum2) return;
  165.     short digit = 0, carry = 0;
  166.     bignumber* prev = *BigNum1, * temp = *BigNum1;
  167.     bignumber* p = nullptr;
  168.     while ((temp != nullptr))
  169.     {
  170.         //учитываем перенос
  171.         digit = carry;
  172.         if (BigNum2 != nullptr) {
  173.             digit = digit + BigNum2->digit;
  174.             BigNum2 = BigNum2->next; //переходим к следующей цифре 2 числа
  175.         }
  176.         if (temp != nullptr) {
  177.             digit = digit + temp->digit;
  178.             prev = temp;
  179.             temp = temp->next;
  180.         }
  181.         //вычисляем новый перенос
  182.         carry = digit / 10;
  183.         //вычисляем цифру текущего разряда
  184.         digit = digit % 10;
  185.         prev->digit = digit;
  186.     }
  187.     while ((carry > 0) || (BigNum2 != nullptr))//создаем новые разряды в 1 числе
  188.     {
  189.         digit = carry;
  190.         if (BigNum2 != nullptr) {
  191.             digit = digit + BigNum2->digit;
  192.             BigNum2 = BigNum2->next; //переходим к следующей цифре 2 числа
  193.         }
  194.         //вычисляем новый перенос
  195.         carry = digit / 10;
  196.         //вычисляем цифру текущего разряда
  197.         digit = digit % 10;
  198.         p = new bignumber;
  199.         p->digit = digit;
  200.         p->next = nullptr;
  201.         if (prev != nullptr) {//был предшествующий узел
  202.             prev->next = p;
  203.         }
  204.         else {
  205.             if (*BigNum1 == nullptr) *BigNum1 = p;
  206.         }
  207.         prev = p;
  208.  
  209.     }
  210.  
  211. }
  212.  
  213. void subtract(bignumber** BigNum1, bignumber* BigNum2)
  214. {
  215.     if (!BigNum2) return;
  216.     short digit = 0, borrow = 0;
  217.     bignumber* prev = *BigNum1, * temp = *BigNum1;
  218.     bignumber* p = nullptr;
  219.     while (temp != nullptr)
  220.     {
  221.         // Учитываем заем
  222.         digit = borrow + temp->digit;
  223.         if (BigNum2 != nullptr) {
  224.             digit -= BigNum2->digit;
  225.             BigNum2 = BigNum2->next; // Переходим к следующей цифре второго числа
  226.         }
  227.         // Вычисляем новый заем
  228.         borrow = digit < 0 ? -1 : 0;
  229.         // Вычисляем цифру текущего разряда
  230.         digit = (digit + 10) % 10;
  231.         prev->digit = digit;
  232.         temp = temp->next;
  233.         prev = temp;
  234.     }
  235. }
  236.  
  237. bignumber* Mult(bignumber* BigNum, int N, int carry)
  238. {
  239.     int digit = carry;//прибавляем перенос
  240.     bignumber* p = nullptr;
  241.     if ((carry != 0) || (BigNum != nullptr))
  242.     {
  243.         if (BigNum != nullptr)
  244.         { //умножаем цифру числа на N
  245.             digit = digit + N * (BigNum->digit);
  246.             //переходим к следующей цифре
  247.             BigNum = BigNum->next;
  248.         }
  249.         //вычисляем новый перенос
  250.         carry = digit / 10;
  251.         //вычисляем цифру текущего разряда
  252.         digit = digit % 10;
  253.         //создаем этот разряд
  254.         p = new bignumber;
  255.         p->digit = digit;
  256.         //остальные разряды вычисляем рекурсивно
  257.         p->next = Mult(BigNum, N, carry);
  258.     }
  259.     return p;
  260. }
  261. void shift(bignumber** BigNum, int n) //поразрядный сдвиг на n (домножение на 10^n)
  262. {
  263.     bignumber* temp = *BigNum;
  264.     int i;
  265.     for (i = 0; i < n; i++)
  266.     {
  267.         //создаем новый разряд
  268.         temp = new bignumber;
  269.         temp->digit = 0;
  270.         //подцепляем предыдущие разряды
  271.         temp->next = *BigNum;
  272.         *BigNum = temp;
  273.     }
  274. }
  275. bignumber* BigMult(bignumber* BigNum1, bignumber* BigNum2)
  276. {
  277.     bignumber* p = nullptr, * temp = nullptr;
  278.     if (BigNum1 != nullptr)
  279.     {
  280.         int k = 0; //сдвиг разрядов при умножении
  281.         p = new bignumber;
  282.         p->digit = 0;
  283.         p->next = nullptr;
  284.         while (BigNum2 != nullptr)
  285.         {
  286.             temp = Mult(BigNum1, BigNum2->digit, 0);//умножение 1-го числа на текущую цифру 2го
  287.  
  288.             shift(&temp, k);
  289.             addto(&p, temp);
  290.             clear(&temp);
  291.             temp = nullptr;
  292.             BigNum2 = BigNum2->next;
  293.             k++;
  294.         }
  295.     }
  296.     return p;
  297. }
  298.  
  299. // с округлением вниз
  300. bignumber* div(bignumber* sa, bignumber *ba){ // a - b * k = 0 <=> a = bk
  301.     bignumber *zero, *bi, *one, *a, *b;
  302.     a = create("1");
  303.     b = create("1");
  304.     a = BigMult(a, sa);
  305.     b = BigMult(b, ba);
  306.     // скопировал
  307.     zero = create("0");
  308.     bi = create("0");
  309.     one = create("1");
  310.     while(More(a, zero)){ // while(a > 0) / while(a > b) <=>
  311.         addto(&zero, b);
  312.         addto(&bi, one);
  313.     }
  314. //    cout << "xueta:";
  315. //    print(bi);
  316. //    cout << endl;
  317.     return bi;
  318. }
  319.  
  320. void solve(){
  321.     string n = "128";
  322.  
  323.     cin >> n;
  324.     bignumber *bn, *bi, *bd, *one;
  325.     bn = create(n);
  326.     bi = create("2");
  327.     one = create("1");
  328.     while(More(bn, one)){ // n >= 1
  329.         bignumber *divider;
  330.  
  331.         divider = div(bn, bi);
  332.         while(Eq(BigMult(divider, bi ), bn)){ // если делится нацело
  333.  
  334.             divider = div(bn, bi); // частное bn/bi с округлением вниз
  335.  
  336.             print(bi); // простой делитель
  337.             cout << "\n";
  338.             bn = divider; // разложил
  339.             divider = div(bn, bi); // для проверки, делится ли то, которое сейчас
  340.         }
  341.         addto(&bi, one); // смиотрим некст
  342.         clear(&divider);
  343.     }
  344.     clear(&bn); clear(&bi); clear(&bd); clear(&one);
  345.  
  346. }
  347.  
  348. int main() {
  349.     ios::sync_with_stdio(0);
  350.     cin.tie(0);
  351. #ifdef DEBUG
  352. //    freopen("text.txt", "r", stdin);
  353. //    freopen("output.txt", "w", stdout);
  354. #endif
  355.     solve();
  356.     return 1;
  357. }
  358.  
  359.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement