TrickmanOff

Karatsuba non-recursion

Sep 23rd, 2019
326
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.08 KB | None | 0 0
  1. #pragma optimization_level 3
  2. #pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math,O3")
  3. #include <iostream>
  4. #include <algorithm>
  5. #include <fstream>
  6. #include <vector>
  7. #include <queue>
  8. #include <stack>
  9. #include <functional>
  10. #include <set>
  11. #include <map>
  12. #include <math.h>
  13. #include <cmath>
  14. #include <string>
  15. #include <time.h>
  16. #include <random>
  17. #include <unordered_set>
  18. #include <unordered_map>
  19. #include <bitset>
  20. #include <string.h>
  21. #include <complex>
  22. #include <ctime>
  23. using namespace std;
  24.  
  25. #define fast cin.tie(0);cout.tie(0);cin.sync_with_stdio(0);cout.sync_with_stdio(0);
  26. //#define cin in
  27. //#define cout out
  28. #define pii pair<int,int>
  29. //#define ll long long
  30. #define db double
  31. #define ld long double
  32. #define uset unordered_set
  33. #define umap unordered_map
  34. #define vec vector
  35. #define ms multiset
  36. #define pb push_back
  37. #define pll pair<ll,ll>
  38. #define pdd pair<ld, ld>
  39. #define pq priority_queue
  40. #define umap unordered_map
  41. #define uset unordered_set
  42. #define pnn pair<Node*, Node*>
  43. #define uid uniform_int_distribution
  44.  
  45. typedef long long ll;
  46. typedef unsigned int uint;
  47.  
  48. ifstream in("input.txt");
  49. ofstream out("output.txt");
  50.  
  51. //simple polynomial multiplication O(N^2), given polynoms have to be formatted for Karatsuba algorithm
  52. void simp_mult(vector<uint>& a, vector<uint>& b, vector<uint>& res) {
  53.     int n = a.size();
  54.     vector<uint> ans(2 * n - 1, 0);
  55.     for (int i = 0; i < n; i++)
  56.         for (int j = 0; j < n; j++)
  57.             ans[i + j] = ans[i + j] + a[i] * b[j];
  58.  
  59.     res.resize(2 * n - 1);
  60.     for (int i = 0; i < ans.size(); i++)
  61.         res[i] = ans[i];
  62. }
  63.  
  64. //simple polynomial addition O(N), given polynoms have to be formatted for Karatsuba algorithm
  65. void simp_add(vector<uint>& a, vector<uint>& b, vector<uint>& res) {
  66.     int n = a.size();
  67.     res.resize(n);
  68.  
  69.     for (int i = 0; i < n; i++)
  70.         res[i] = a[i] + b[i];
  71. }
  72.  
  73. //simple polynomial substraction O(N), given polynoms have to be formatted for Karatsuba algorithm
  74. void simp_subs(vector<uint>& a, vector<uint>& b, vector<uint>& res) {
  75.     int n = a.size();
  76.     res.resize(n);
  77.  
  78.     for (int i = 0; i < n; i++)
  79.         res[i] = a[i] - b[i];
  80. }
  81.  
  82. //format given polynoms for Karatsuba algorithm
  83. void format(vector<uint>& a, vector<uint>& b) {
  84.     int l = max(a.size(), b.size());
  85.     int n = 1;
  86.     while (n < l)
  87.         n <<= 1;
  88.  
  89.     a.resize(n);
  90.     b.resize(n);
  91. }
  92.  
  93. struct unit {
  94.     vector<uint>* a, * b, * res, * t1, * t2, * gamma;
  95.     int sz;
  96.     unit(vector<uint>* a, vector<uint>* b, vector<uint>* res) : a(a), b(b), res(res) {
  97.         t1 = new vector<uint>();
  98.         t2 = new vector<uint>();
  99.         gamma = new vector<uint>();
  100.         sz = a->size();
  101.     }
  102. };
  103.  
  104. void cnt(vector<uint>& res, vector<uint>& t1, vector<uint>& t2, vector<uint>& t3, int n) {
  105.     int n2 = n / 2;
  106.  
  107.     res.assign((n << 1) - 1, 0);
  108.  
  109.     for (int i = 0; i < t1.size(); i++)
  110.         res[i] = t1[i];
  111.  
  112.     for (int i = 0; i < t3.size(); i++)
  113.         res[i + n2] = res[i + n2] + t3[i];
  114.  
  115.     for (int i = 0; i < t2.size(); i++)
  116.         res[i + n] = res[i + n] + t2[i];
  117. }
  118.  
  119. const int LIM = 512;
  120.  
  121. void karatsuba(vector<uint>& A, vector<uint>& B, vector<uint>& res) {
  122.     deque<unit> units;
  123.  
  124.     int p = 0;
  125.     units.push_back(unit(&A, &B, &res));
  126.  
  127.     //идём в одну сторону
  128.  
  129.     while (p < units.size()) {
  130.         unit cur = units[p++];
  131.  
  132.         vector<uint>* A, * B, * res, * t1, * t2, * gamma;
  133.         A = cur.a, B = cur.b, res = cur.res, t1 = cur.t1, t2 = cur.t2, gamma = cur.gamma;
  134.  
  135.         int n = cur.sz;
  136.         if (n <= LIM)
  137.             continue;
  138.  
  139.         int n2 = (n >> 1);
  140.  
  141.         vector<uint>* alpha = new vector<uint>(A->begin(), A->begin() + n2);
  142.         vector<uint>* a = new vector<uint>(A->begin() + n2, A->end());
  143.         vector<uint>* beta = new vector<uint>(B->begin(), B->begin() + n2);
  144.         vector<uint>* b = new vector<uint>(B->begin() + n2, B->end());
  145.  
  146.         units.push_back(unit(alpha, beta, t1));
  147.         units.push_back(unit(a, b, t2));
  148.  
  149.         vector<uint>* f_sum = new vector<uint>();
  150.         vector<uint>* s_sum = new vector<uint>();
  151.         simp_add(*alpha, *a, *f_sum);
  152.         simp_add(*beta, *b, *s_sum);
  153.         units.push_back(unit(f_sum, s_sum, gamma));
  154.  
  155.         vector<uint> t3;
  156.         simp_subs(*gamma, *t1, t3);
  157.         simp_subs(t3, *t2, t3);
  158.  
  159.         res->assign((n << 1) - 1, 0);
  160.  
  161.     }
  162.     p--;
  163.     //возвращаемся и считаем ответы
  164.     while (p >= 0) {
  165.         unit cur = units[p--];
  166.  
  167.         int n = cur.sz;
  168.         if (n <= LIM) {
  169.             simp_mult(*cur.a, *cur.b, *cur.res);
  170.             continue;
  171.         }
  172.  
  173.         vector<uint>* A, * B, * res, * t1, * t2, * gamma;
  174.         A = cur.a, B = cur.b, res = cur.res, t1 = cur.t1, t2 = cur.t2, gamma = cur.gamma;
  175.  
  176.         vector<uint> t3;
  177.         simp_subs(*gamma, *t1, t3);
  178.         simp_subs(t3, *t2, t3);
  179.  
  180.         cnt(*res, *t1, *t2, t3, n);
  181.  
  182.     }
  183. }
  184.  
  185. void read_vec(vector<uint>& a, string& s) {
  186.     int num = 0;
  187.     for (char x : s) {
  188.         if (x == ' ') {
  189.             a.push_back(num);
  190.             num = 0;
  191.             continue;
  192.         }
  193.  
  194.         num = num * 10 + x - '0';
  195.     }
  196.     a.push_back(num);
  197. }
  198.  
  199.  
  200. int main()
  201. {
  202.     fast;
  203.     string s;
  204.     getline(cin, s);
  205.  
  206.     int fin_n = 0;
  207.  
  208.     vector<uint> res;
  209.     read_vec(res, s);
  210.     fin_n += res.size() - 1;
  211.  
  212.     while (getline(cin, s)) {
  213.         vector<uint> b;
  214.         read_vec(b, s);
  215.         fin_n += b.size() - 1;
  216.  
  217.         format(res, b);
  218.         karatsuba(res, b, res);
  219.     }
  220.  
  221.     for (int i = 0; i <= fin_n; i++)
  222.         cout << res[i] << ' ';
  223. }
Advertisement
Add Comment
Please, Sign In to add comment