Advertisement
Ksenia_C

Elliptic curves

Sep 2nd, 2021
817
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 21.37 KB | None | 0 0
  1. // I am too sad about life to write good code.
  2. // Right when I get well I will rewrite it.
  3. #define _CRT_SECURE_NO_WARNINGS
  4.  
  5. #include <algorithm>
  6. #include <complex>
  7. #include <iostream>
  8. #include <vector>
  9. #include <string>
  10. #include <time.h>
  11. #include <iomanip>
  12.  
  13. using namespace std;
  14. typedef unsigned long long ll;
  15.  
  16. namespace fft {
  17.     using cpx = complex<double>;
  18.     const double PI = acos(-1);
  19.     vector<cpx> roots = { {0, 0}, {1, 0} };
  20.  
  21.     void ensure_capacity(int min_capacity) {
  22.         for (int len = roots.size(); len < min_capacity; len *= 2) {
  23.             for (int i = len >> 1; i < len; i++) {
  24.                 roots.emplace_back(roots[i]);
  25.                 double angle = 2 * PI * (2 * i + 1 - len) / (len * 2);
  26.                 roots.emplace_back(cos(angle), sin(angle));
  27.             }
  28.         }
  29.     }
  30.  
  31.     void fft(vector<cpx>& z, bool inverse) {
  32.         int n = z.size();
  33.         ensure_capacity(n);
  34.         for (unsigned i = 1, j = 0; i < n; i++) {
  35.             int bit = n >> 1;
  36.             for (; j >= bit; bit >>= 1)
  37.                 j -= bit;
  38.             j += bit;
  39.             if (i < j)
  40.                 swap(z[i], z[j]);
  41.         }
  42.         for (int len = 1; len < n; len <<= 1) {
  43.             for (int i = 0; i < n; i += len * 2) {
  44.                 for (int j = 0; j < len; j++) {
  45.                     cpx root = inverse ? conj(roots[j + len]) : roots[j + len];
  46.                     cpx u = z[i + j];
  47.                     cpx v = z[i + j + len] * root;
  48.                     z[i + j] = u + v;
  49.                     z[i + j + len] = u - v;
  50.                 }
  51.             }
  52.         }
  53.         if (inverse)
  54.             for (int i = 0; i < n; i++)
  55.                 z[i] /= n;
  56.     }
  57.  
  58.     vector<int> multiply_bigint(const vector<int>& a, const vector<int>& b, int base) {
  59.         int need = a.size() + b.size();
  60.         int n = 1;
  61.         while (n < need)
  62.             n <<= 1;
  63.         vector<cpx> p(n);
  64.         for (size_t i = 0; i < n; i++) {
  65.             p[i] = cpx(i < a.size() ? a[i] : 0, i < b.size() ? b[i] : 0);
  66.         }
  67.         fft(p, false);
  68.         // a[w[k]] = (p[w[k]] + conj(p[w[n-k]])) / 2
  69.         // b[w[k]] = (p[w[k]] - conj(p[w[n-k]])) / (2*i)
  70.         vector<cpx> ab(n);
  71.         cpx r(0, -0.25);
  72.         for (int i = 0; i < n; i++) {
  73.             int j = (n - i) & (n - 1);
  74.             ab[i] = (p[i] * p[i] - conj(p[j] * p[j])) * r;
  75.         }
  76.         fft(ab, true);
  77.         vector<int> result(need);
  78.         long long carry = 0;
  79.         for (int i = 0; i < need; i++) {
  80.             long long d = (long long)(ab[i].real() + 0.5) + carry;
  81.             carry = d / base;
  82.             result[i] = d % base;
  83.         }
  84.         return result;
  85.     }
  86.  
  87.     vector<int> multiply_mod(const vector<int>& a, const vector<int>& b, int m) {
  88.         int need = a.size() + b.size() - 1;
  89.         int n = 1;
  90.         while (n < need)
  91.             n <<= 1;
  92.         vector<cpx> A(n);
  93.         for (size_t i = 0; i < a.size(); i++) {
  94.             int x = (a[i] % m + m) % m;
  95.             A[i] = cpx(x & ((1 << 15) - 1), x >> 15);
  96.         }
  97.         fft(A, false);
  98.  
  99.         vector<cpx> B(n);
  100.         for (size_t i = 0; i < b.size(); i++) {
  101.             int x = (b[i] % m + m) % m;
  102.             B[i] = cpx(x & ((1 << 15) - 1), x >> 15);
  103.         }
  104.         fft(B, false);
  105.  
  106.         vector<cpx> fa(n);
  107.         vector<cpx> fb(n);
  108.         for (int i = 0, j = 0; i < n; i++, j = n - i) {
  109.             cpx a1 = (A[i] + conj(A[j])) * cpx(0.5, 0);
  110.             cpx a2 = (A[i] - conj(A[j])) * cpx(0, -0.5);
  111.             cpx b1 = (B[i] + conj(B[j])) * cpx(0.5, 0);
  112.             cpx b2 = (B[i] - conj(B[j])) * cpx(0, -0.5);
  113.             fa[i] = a1 * b1 + a2 * b2 * cpx(0, 1);
  114.             fb[i] = a1 * b2 + a2 * b1;
  115.         }
  116.  
  117.         fft(fa, true);
  118.         fft(fb, true);
  119.         vector<int> res(need);
  120.         for (int i = 0; i < need; i++) {
  121.             long long aa = (long long)(fa[i].real() + 0.5);
  122.             long long bb = (long long)(fb[i].real() + 0.5);
  123.             long long cc = (long long)(fa[i].imag() + 0.5);
  124.             res[i] = (aa % m + (bb % m << 15) + (cc % m << 30)) % m;
  125.         }
  126.         return res;
  127.     }
  128. }
  129.  
  130. namespace bigint_space {
  131.     constexpr int digits(int base) noexcept {
  132.         return base <= 1 ? 0 : 1 + digits(base / 10);
  133.     }
  134.  
  135.     constexpr int base = 1000'000'000;
  136.     constexpr int base_digits = digits(base);
  137.  
  138.     constexpr int fft_base = 10'000;  // fft_base^2 * n / fft_base_digits <= 10^15 for double
  139.    constexpr int fft_base_digits = digits(fft_base);
  140.  
  141.    struct bigint {
  142.        // value == 0 is represented by empty z
  143.        vector<int> z;  // digits
  144.  
  145.        // sign == 1 <==> value >= 0
  146.        // sign == -1 <==> value < 0
  147.        int sign;
  148.  
  149.        bigint(long long v = 0) { *this = v; }
  150.  
  151.        bigint& operator=(long long v) {
  152.            sign = v < 0 ? -1 : 1;
  153.            v *= sign;
  154.            z.clear();
  155.            for (; v > 0; v = v / base)
  156.                z.push_back((int)(v % base));
  157.            return *this;
  158.        }
  159.  
  160.        bigint(const string& s) { read(s); }
  161.  
  162.        bigint& operator+=(const bigint& other) {
  163.            if (sign == other.sign) {
  164.                for (int i = 0, carry = 0; i < other.z.size() || carry; ++i) {
  165.                    if (i == z.size())
  166.                        z.push_back(0);
  167.                    z[i] += carry + (i < other.z.size() ? other.z[i] : 0);
  168.                    carry = z[i] >= base;
  169.                    if (carry)
  170.                        z[i] -= base;
  171.                }
  172.            } else if (other != 0 /* prevent infinite loop */) {
  173.                *this -= -other;
  174.            }
  175.            return *this;
  176.        }
  177.  
  178.        friend bigint operator+(bigint a, const bigint& b) {
  179.            a += b;
  180.            return a;
  181.        }
  182.  
  183.        bigint& operator-=(const bigint& other) {
  184.            if (sign == other.sign) {
  185.                if ((sign == 1 && *this >= other) || (sign == -1 && *this <= other)) {
  186.                    for (int i = 0, carry = 0; i < other.z.size() || carry; ++i) {
  187.                        z[i] -= carry + (i < other.z.size() ? other.z[i] : 0);
  188.                        carry = z[i] < 0;
  189.                        if (carry)
  190.                            z[i] += base;
  191.                    }
  192.                    trim();
  193.                } else {
  194.                    *this = other - *this;
  195.                    this->sign = -this->sign;
  196.                }
  197.            } else {
  198.                *this += -other;
  199.            }
  200.            return *this;
  201.        }
  202.  
  203.        friend bigint operator-(bigint a, const bigint& b) {
  204.            a -= b;
  205.            return a;
  206.        }
  207.  
  208.        bigint& operator*=(int v) {
  209.            if (v < 0)
  210.                sign = -sign, v = -v;
  211.            for (int i = 0, carry = 0; i < z.size() || carry; ++i) {
  212.                if (i == z.size())
  213.                    z.push_back(0);
  214.                long long cur = (long long)z[i] * v + carry;
  215.                carry = (int)(cur / base);
  216.                z[i] = (int)(cur % base);
  217.            }
  218.            trim();
  219.            return *this;
  220.        }
  221.  
  222.        bigint operator*(int v) const { return bigint(*this) *= v; }
  223.  
  224.        friend pair<bigint, bigint> divmod(const bigint& a1, const bigint& b1) {
  225.            int norm = base / (b1.z.back() + 1);
  226.            bigint a = a1.abs() * norm;
  227.            bigint b = b1.abs() * norm;
  228.            bigint q, r;
  229.            q.z.resize(a.z.size());
  230.  
  231.            for (int i = (int)a.z.size() - 1; i >= 0; i--) {
  232.                r *= base;
  233.                r += a.z[i];
  234.                int s1 = b.z.size() < r.z.size() ? r.z[b.z.size()] : 0;
  235.                int s2 = b.z.size() - 1 < r.z.size() ? r.z[b.z.size() - 1] : 0;
  236.                int d = (int)(((long long)s1 * base + s2) / b.z.back());
  237.                r -= b * d;
  238.                while (r < 0)
  239.                    r += b, --d;
  240.                q.z[i] = d;
  241.            }
  242.  
  243.            q.sign = a1.sign * b1.sign;
  244.            r.sign = a1.sign;
  245.            q.trim();
  246.            r.trim();
  247.            return { q, r / norm };
  248.        }
  249.  
  250.        friend bigint sqrt(const bigint& a1) {
  251.            bigint a = a1;
  252.            while (a.z.empty() || a.z.size() % 2 == 1)
  253.                a.z.push_back(0);
  254.  
  255.            int n = a.z.size();
  256.  
  257.            int firstDigit = (int)::sqrt((double)a.z[n - 1] * base + a.z[n - 2]);
  258.            int norm = base / (firstDigit + 1);
  259.            a *= norm;
  260.            a *= norm;
  261.            while (a.z.empty() || a.z.size() % 2 == 1)
  262.                a.z.push_back(0);
  263.  
  264.            bigint r = (long long)a.z[n - 1] * base + a.z[n - 2];
  265.            firstDigit = (int)::sqrt((double)a.z[n - 1] * base + a.z[n - 2]);
  266.            int q = firstDigit;
  267.            bigint res;
  268.  
  269.            for (int j = n / 2 - 1; j >= 0; j--) {
  270.                for (;; --q) {
  271.                    bigint r1 = (r - (res * 2 * base + q) * q) * base * base +
  272.                        (j > 0 ? (long long)a.z[2 * j - 1] * base + a.z[2 * j - 2] : 0);
  273.                    if (r1 >= 0) {
  274.                        r = r1;
  275.                        break;
  276.                    }
  277.                }
  278.                res *= base;
  279.                res += q;
  280.  
  281.                if (j > 0) {
  282.                    int d1 = res.z.size() + 2 < r.z.size() ? r.z[res.z.size() + 2] : 0;
  283.                    int d2 = res.z.size() + 1 < r.z.size() ? r.z[res.z.size() + 1] : 0;
  284.                    int d3 = res.z.size() < r.z.size() ? r.z[res.z.size()] : 0;
  285.                    q = (int)(((long long)d1 * base * base + (long long)d2 * base + d3) / (firstDigit * 2));
  286.                }
  287.            }
  288.  
  289.            res.trim();
  290.            return res / norm;
  291.        }
  292.  
  293.        bigint operator/(const bigint& v) const { return divmod(*this, v).first; }
  294.  
  295.        bigint operator%(const bigint& v) const { return divmod(*this, v).second; }
  296.  
  297.        bigint& operator/=(int v) {
  298.            if (v < 0)
  299.                sign = -sign, v = -v;
  300.            for (int i = (int)z.size() - 1, rem = 0; i >= 0; --i) {
  301.                long long cur = z[i] + rem * (long long)base;
  302.                z[i] = (int)(cur / v);
  303.                rem = (int)(cur % v);
  304.            }
  305.            trim();
  306.            return *this;
  307.        }
  308.  
  309.        bigint operator/(int v) const { return bigint(*this) /= v; }
  310.  
  311.        int operator%(int v) const {
  312.            if (v < 0)
  313.                v = -v;
  314.            int m = 0;
  315.            for (int i = (int)z.size() - 1; i >= 0; --i)
  316.                m = (int)((z[i] + m * (long long)base) % v);
  317.            return m * sign;
  318.        }
  319.  
  320.        bigint& operator*=(const bigint& v) {
  321.            *this = *this * v;
  322.            return *this;
  323.        }
  324.  
  325.        bigint& operator/=(const bigint& v) {
  326.            *this = *this / v;
  327.            return *this;
  328.        }
  329.  
  330.        bigint& operator%=(const bigint& v) {
  331.            *this = *this % v;
  332.            return *this;
  333.        }
  334.  
  335.        bool operator<(const bigint& v) const {
  336.            if (sign != v.sign)
  337.                return sign < v.sign;
  338.            if (z.size() != v.z.size())
  339.                return z.size() * sign < v.z.size()* v.sign;
  340.            for (int i = (int)z.size() - 1; i >= 0; i--)
  341.                if (z[i] != v.z[i])
  342.                    return z[i] * sign < v.z[i] * sign;
  343.            return false;
  344.        }
  345.  
  346.        bool operator>(const bigint& v) const { return v < *this; }
  347.  
  348.        bool operator<=(const bigint& v) const { return !(v < *this); }
  349.  
  350.        bool operator>=(const bigint& v) const { return !(*this < v); }
  351.  
  352.        bool operator==(const bigint& v) const { return sign == v.sign && z == v.z; }
  353.  
  354.        bool operator!=(const bigint& v) const { return !(*this == v); }
  355.  
  356.        void trim() {
  357.            while (!z.empty() && z.back() == 0)
  358.                z.pop_back();
  359.            if (z.empty())
  360.                sign = 1;
  361.        }
  362.  
  363.        bool isZero() const { return z.empty(); }
  364.  
  365.        friend bigint operator-(bigint v) {
  366.            if (!v.z.empty())
  367.                v.sign = -v.sign;
  368.            return v;
  369.        }
  370.  
  371.        bigint abs() const { return sign == 1 ? *this : -*this; }
  372.  
  373.        long long longValue() const {
  374.            long long res = 0;
  375.            for (int i = (int)z.size() - 1; i >= 0; i--)
  376.                res = res * base + z[i];
  377.            return res * sign;
  378.        }
  379.  
  380.        friend bigint gcd(const bigint& a, const bigint& b) { return b.isZero() ? a : gcd(b, a % b); }
  381.  
  382.        friend bigint lcm(const bigint& a, const bigint& b) { return a / gcd(a, b) * b; }
  383.  
  384.        void read(const string& s) {
  385.            sign = 1;
  386.            z.clear();
  387.            int pos = 0;
  388.            while (pos < s.size() && (s[pos] == '-' || s[pos] == '+')) {
  389.                if (s[pos] == '-')
  390.                    sign = -sign;
  391.                ++pos;
  392.            }
  393.            for (int i = (int)s.size() - 1; i >= pos; i -= base_digits) {
  394.                int x = 0;
  395.                for (int j = max(pos, i - base_digits + 1); j <= i; j++)
  396.                    x = x * 10 + s[j] - '0';
  397.                z.push_back(x);
  398.            }
  399.            trim();
  400.        }
  401.  
  402.        friend istream& operator>>(istream& stream, bigint& v) {
  403.            string s;
  404.            stream >> s;
  405.            v.read(s);
  406.            return stream;
  407.        }
  408.  
  409.        friend ostream& operator<<(ostream& stream, const bigint& v) {
  410.            if (v.sign == -1)
  411.                stream << '-';
  412.            stream << (v.z.empty() ? 0 : v.z.back());
  413.            for (int i = (int)v.z.size() - 2; i >= 0; --i)
  414.                stream << setw(base_digits) << setfill('0') << v.z[i];
  415.            return stream;
  416.        }
  417.  
  418.        static vector<int> convert_base(const vector<int>& a, int old_digits, int new_digits) {
  419.            vector<long long> p(max(old_digits, new_digits) + 1);
  420.            p[0] = 1;
  421.            for (int i = 1; i < p.size(); i++)
  422.                p[i] = p[i - 1] * 10;
  423.            vector<int> res;
  424.            long long cur = 0;
  425.            int cur_digits = 0;
  426.            for (int v : a) {
  427.                cur += v * p[cur_digits];
  428.                cur_digits += old_digits;
  429.                while (cur_digits >= new_digits) {
  430.                    res.push_back(int(cur % p[new_digits]));
  431.                    cur /= p[new_digits];
  432.                    cur_digits -= new_digits;
  433.                }
  434.            }
  435.            res.push_back((int)cur);
  436.            while (!res.empty() && res.back() == 0)
  437.                res.pop_back();
  438.            return res;
  439.        }
  440.  
  441.        bigint operator*(const bigint& v) const {
  442.            if (min(z.size(), v.z.size()) < 150)
  443.                return mul_simple(v);
  444.            bigint res;
  445.            res.sign = sign * v.sign;
  446.            res.z = fft::multiply_bigint(convert_base(z, base_digits, fft_base_digits),
  447.                convert_base(v.z, base_digits, fft_base_digits), fft_base);
  448.            res.z = convert_base(res.z, fft_base_digits, base_digits);
  449.            res.trim();
  450.            return res;
  451.        }
  452.  
  453.        bigint mul_simple(const bigint& v) const {
  454.            bigint res;
  455.            res.sign = sign * v.sign;
  456.            res.z.resize(z.size() + v.z.size());
  457.            for (int i = 0; i < z.size(); ++i)
  458.                if (z[i])
  459.                    for (int j = 0, carry = 0; j < v.z.size() || carry; ++j) {
  460.                        long long cur = res.z[i + j] + (long long)z[i] * (j < v.z.size() ? v.z[j] : 0) + carry;
  461.                        carry = (int)(cur / base);
  462.                        res.z[i + j] = (int)(cur % base);
  463.                    }
  464.            res.trim();
  465.            return res;
  466.        }
  467.    };
  468. }
  469.  
  470. int sz = 7;
  471. ll max_rank = 10'000'000;
  472. using namespace bigint_space;
  473. bigint p, a, b;
  474.  
  475. template<typename bigint_T, typename T>
  476. bigint_T mpow(const bigint_T& a, T st) {
  477.    if (st == 0) return 1;
  478.    bigint_T res = mpow(a, st / 2);
  479.    res = res * res;
  480.    if (st % 2) res = res * a;
  481.    return res;
  482. }
  483.  
  484. class Zp {
  485.    bigint val;
  486.    public:
  487.    Zp() {}
  488.    Zp(ll num) : val(num) {}
  489.    Zp(bigint val) : val(val) {}
  490.    Zp operator+ (const Zp& other) const {
  491.        return (this->val + other.val) % p;
  492.    }
  493.    Zp operator- (const Zp& other) const {
  494.        return (this->val + p - other.val) % p;
  495.    }
  496.    Zp operator* (const Zp& other) const {
  497.        return (this->val * other.val) % p;
  498.    }
  499.    bool operator==(const Zp& other) const {
  500.        return this->val == other.val;
  501.    }
  502.    bool operator>(const Zp& other) const {
  503.        return this->val > other.val;
  504.    }
  505.  
  506.    Zp rev(const Zp& num) const {
  507.        return mpow(num, p - bigint(2));
  508.    }
  509.  
  510.    Zp operator/(const Zp& d) const {
  511.        return Zp((*this * rev(d)).val % p);
  512.    }
  513.  
  514.    bigint get_val() const {
  515.        return val;
  516.    }
  517. };
  518.  
  519. class Point {
  520.    bool is_infty = true;
  521.    Zp x, y;
  522.    public:
  523.    Point() {};
  524.    Point(bigint x, bigint y) : x(x), y(y), is_infty(false) {}
  525.    Point(Zp x, Zp y) : x(x), y(y), is_infty(false) {}
  526.  
  527.    Point operator-() const {
  528.        if (is_infty) return (*this);
  529.        return Point(x, Zp(0) - y);
  530.    }
  531.  
  532.    Point operator+(const Point& other) const {
  533.        Zp k;
  534.        if (other.is_infty) return *this;
  535.        if (this->is_infty) return other;
  536.        if (this->x == other.x) {
  537.            if ((this->y + other.y).get_val() % p == bigint(0)) {
  538.                return Point();
  539.            }
  540.            k = (Zp(3) * this->x * this->x + a) / Zp(2) / this->y;
  541.        } else {
  542.            k = (this->y - other.y) / (this->x - other.x);
  543.        }
  544.        Zp x3 = k * k - this->x - other.x;
  545.        return Point(x3, k * (x3 - this->x) + this->y);
  546.    }
  547.    bool is_infty_() const {
  548.        return is_infty;
  549.    }
  550.    bigint get_x() const {
  551.        return x.get_val();
  552.    }
  553.    bigint get_y() const {
  554.        return y.get_val();
  555.    }
  556.  
  557. };
  558.  
  559. ostream& operator<<(ostream& os, const Point& num)
  560. {
  561.    if (num.is_infty_()) os << "Z";
  562.    else {
  563.        os << num.get_x() << ' ' << num.get_y();
  564.    }
  565.    return os;
  566. }
  567.  
  568. int char_to_number(char symbol) {
  569.    if (symbol >= 48 && symbol <= 57)
  570.        return symbol - 48;
  571.    if (symbol >= 65 && symbol <= 90)
  572.        return symbol - 55;
  573.    if (symbol >= 97 && symbol <= 122)
  574.        return symbol - 61;
  575.    if (symbol == '_')
  576.        return 62;
  577.    if (symbol == 46)
  578.        return 63;
  579.    return 64;
  580. }
  581.  
  582. char number_to_char(int num) {
  583.    if (num >= 48 - 48 && num <= 57 - 48)
  584.        return num + 48;
  585.    if (num >= 65 - 55 && num <= 90 - 55)
  586.        return num + 55;
  587.    if (num >= 97 - 61 && num <= 122 - 61)
  588.        return num + 61;
  589.    if (num == 62)
  590.        return '_';
  591.    if (num == 63)
  592.        return 46;
  593.    return '\0';
  594. }
  595.  
  596. bigint from_any_to_10(vector<ll>& num, const bigint& any) {
  597.    bigint res(0);
  598.    bigint st(1);
  599.    for (auto b : num) {
  600.        res = res + st * b;
  601.        st = st * any;
  602.    }
  603.    return res;
  604. }
  605.  
  606. vector<bigint> from_10_to_any(bigint num, const bigint& any) {
  607.    vector<bigint> res;
  608.    if (num == 0) return { 0 };
  609.    while (num > 0) {
  610.        res.push_back(num % any);
  611.        num = num / any;
  612.    }
  613.    return res;
  614. }
  615.  
  616.  
  617. Point mpow(Point& a, bigint st) {
  618.    if (st == 0) return Point();
  619.    Point res = mpow(a, st / 2);
  620.    res = res + res;
  621.    if (st % 2) res = res + a;
  622.    return res;
  623. }
  624.  
  625. bigint get_rand(int len) {
  626.    string val(len, '0');
  627.    for (auto& el : val) {
  628.        el = '0' + rand() % 10;
  629.    }
  630.    return bigint(val);
  631. }
  632.  
  633.  
  634. vector<bigint> convert_to_mes(std::string& str) {
  635.    vector<ll> num64;
  636.    num64.reserve(str.size());
  637.    for (char c : str) {
  638.        num64.push_back(char_to_number(c));
  639.    }
  640.    return from_10_to_any(from_any_to_10(num64, 64), p);
  641. }
  642.  
  643. bigint deg;
  644.  
  645. template<typename T>
  646. T rev(T num) {
  647.    return mpow(num, p, deg - bigint(2));
  648. }
  649.  
  650. void Ell_Gamal_coding(vector<Point>& mes, Point& g, Point& k) {
  651.    int ind = 0;
  652.    for (auto num : mes) {
  653.        bigint st = get_rand(100) % (deg - bigint(1)) + bigint(1);
  654.        cout << mpow(g, st) << '\n' << num + mpow(k, st) << '\n';
  655.        cout << ind << " out of " << mes.size() << endl;
  656.        ++ind;
  657.    }
  658. }
  659.  
  660. void convert_to_str(vector<ll>& mes) {
  661.    auto res = from_10_to_any(from_any_to_10(mes, p), 64);
  662.    for (auto el : res) {
  663.        cout << number_to_char(el % 64);
  664.    }
  665. }
  666.  
  667. int main() {
  668.    srand(time(NULL));
  669.    ios_base::sync_with_stdio(false);
  670.    cin.tie(NULL);
  671.    cout.tie(NULL);
  672.    freopen("input.txt", "r", stdin);
  673.    freopen("output.txt", "w", stdout);
  674.    p = mpow(bigint(2), 256) - mpow(bigint(2), 224) + mpow(bigint(2), 192) + mpow(bigint(2), 96) - bigint(1);
  675.    a = p - bigint(3);
  676.    b = bigint("41058363725152142129326129780047268409114441015993725554835256314039467401291");
  677.    Point g(bigint("48439561293906451759052585252797914202762949526041747995844080717082404635286"),
  678.        bigint("36134250956749795798585127919587881956611106672985015071877198253568414405109"));
  679.    deg = bigint("115792089210356248762697446949407573529996955224135760342422259061068512044369");
  680.    bigint x, y; cin >> x >> y;
  681.    Point k(x, y);
  682.    int n; cin >> n;
  683.    vector<Point> mes(n);
  684.    for (int i = 0; i < n; ++i) {
  685.        string str; cin >> str;
  686.        Zp x_p = convert_to_mes(str)[0];
  687.        Zp y_2 = x_p * x_p * x_p + Zp(a) * x_p + Zp(b);
  688.        bigint p_ = (p + 1) / 4;
  689.        Zp y_p = mpow(y_2, p_);
  690.        mes[i] = Point(x_p, y_p);
  691.    }
  692.    Ell_Gamal_coding(mes, g, k);
  693. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement