Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //#include <cassert>
- //
- ///** Begin fast allocation */
- //const int MAX_MEM = 2e8 + 6e7;
- //int mpos = 0;
- //char mem[MAX_MEM];
- //inline void * operator new (size_t n) {
- // assert((mpos += n) <= MAX_MEM);
- // return (void *)(mem + mpos - n);
- //}
- //void operator delete (void *) noexcept { } // must have!
- //void operator delete (void *, size_t) noexcept { } // must have!
- ///** End fast allocation */
- #pragma GCC optimize("Ofast")
- //#pragma GCC optimize ("unroll-loops")
- //#pragma GCC optimize ("fast-math")
- #pragma GCC target("avx2")
- //#include <bits/stdc++.h>
- #include <iostream>
- #include <algorithm>
- #include <string>
- #include <cmath>
- #include <vector>
- #include <map>
- #include <set>
- #include <list>
- #include <ctime>
- #include <stack>
- #include <queue>
- #include <iomanip>
- #include <cstdlib>
- #include <unordered_map>
- #include <unordered_set>
- #include <cstddef>
- #include <deque>
- #include <cstdio>
- #include <fstream>
- #include <random>
- #include <climits>
- #include <cassert>
- #include <chrono>
- #include <complex>
- using namespace std;
- #define forn(i, j, k) for(int i = (int)(j); i < (int)(k); i++)
- #define forn1(i, j, k) for(int i = (int)(j); i <= (int)(k); i++)
- #define pb push_back
- #define mp make_pair
- #define f first
- #define s second
- #define all(x) begin(x), end(x)
- #define sz(a) ((int)((a).size()))
- #define endl '\n'
- const int INF = 1e9 + 1;
- const long long MOD = 1'000'000'007;
- const long double EPS = 1e-6;
- typedef long long ll;
- typedef unsigned long long ull;
- typedef long double ld;
- std::mt19937 rnd(chrono::system_clock::now().time_since_epoch().count());
- struct hash_function {
- size_t operator() (const pair<int, int>& p) const {
- return p.first ^ p.second;
- }
- };
- double pi = atan2(0., -1.);
- const int LOG = 20;
- const int SZ = (1 << LOG);
- int rev[SZ];
- complex <double> alpha[SZ];
- void initFFT()
- {
- for (int i = 1; i < SZ; i++)
- {
- int it = 0;
- while (!(i & (1 << it) ) ) it++;
- rev[i] = rev[i ^ (1 << it) ] ^ (1 << (LOG - it - 1) );
- }
- for (int i = 0; i < SZ; i++)
- {
- double x = pi * i / (double) SZ;
- alpha[i] = complex <double> (cos(x), sin(x) );
- }
- }
- vector <complex <double> > FFT(vector <complex <double> > &st)
- {
- int n = (int) st.size();
- int k = 0;
- while ( (1 << k) < n) k++;
- if ( (1 << k) != n) throw;
- vector <complex <double> > v, oth;
- oth.resize(n);
- v.resize(n);
- for (int i = 0; i < n; i++)
- v[rev[i] >> (LOG - k) ] = st[i];
- for (int it = LOG - k; it < LOG; it++)
- {
- int half = (n >> (LOG - it) );
- for (int pos = 0; pos < n; pos += (half << 1) )
- {
- for (int i = 0; i < half; i++)
- {
- complex <double> a = v[pos + i];
- complex <double> b = v[pos + half + i] * alpha[i << (LOG - k + LOG - it)];
- oth[pos + i] = a + b;
- oth[pos + half + i] = a - b;
- }
- }
- v.swap(oth);
- }
- return v;
- }
- vector <complex <double> > FFT(const vector <int> &v, int n)
- {
- vector <complex <double> > cv(n, 0.);
- for (int i = 0; i < (int) v.size(); i++)
- cv[i] = complex <double> (v[i] );
- return FFT(cv);
- }
- vector <int> mulFFT(const vector <int> &a, const vector <int> &b)
- {
- int n = (int) a.size() + (int) b.size();
- while (n & (n - 1) ) n++;
- vector <complex <double> > A = FFT(a, n);
- vector <complex <double> > B = FFT(b, n);
- for (int i = 0; i < n; i++)
- A[i] *= B[i];
- B = FFT(A);
- reverse(B.begin() + 1, B.end() );
- for (auto &it : B)
- it /= n;
- // eprintf("1\n");
- vector <int> ans;
- ans.resize(n);
- // eprintf("2\n");
- // eprintf("%d\n", (int) ans.size() );
- // eprintf("%d n = %d\n", (int) B.size(), n);
- for (int i = 0; i < n; i++)
- ans[i] = ((long long) (B[i].real() + 0.5));// % MOD;
- // eprintf("3\n");
- for (int i = 0; i < n - 1; ++i) {
- if (ans[i] >= 10) {
- ans[i + 1] += ans[i] / 10;
- ans[i] %= 10;
- }
- }
- return ans;
- }
- vector<int> to_num(const string& s) {
- vector<int> a;
- for (auto i : s) {
- a.push_back(i - '0');
- }
- reverse(a.begin(), a.end());
- return a;
- }
- vector<int> to_num(int s) {
- vector<int> a;
- while (s > 0) {
- a.push_back(s % 10);
- s /= 10;
- }
- return a;
- }
- bool greater_(const vector<int>& lhs, const vector<int>& rhs) {
- if (lhs.size() > rhs.size()) {
- return true;
- } else if (lhs.size() < rhs.size()) {
- return false;
- }
- for (int i = lhs.size() - 1; i >= 0; --i) {
- if (lhs[i] > rhs[i]) {
- return true;
- } else if (lhs[i] < rhs[i]) {
- return false;
- }
- }
- return false;
- }
- int make2(int n) {
- int pow = 2;
- while (pow < n) {
- pow *= 2;
- }
- return pow;
- }
- void stripe(vector<int>& a) {
- while (a.size() > 1 && a.back() == 0) {
- a.pop_back();
- }
- }
- pair<vector<int>, vector<int>> div21(vector<int> a, vector<int> b, int n);
- pair<vector<int>, vector<int>> div32(vector<int> a, vector<int> b, int n);
- pair<vector<int>, vector<int>> div21(vector<int> a, vector<int> b, int n) { // del, chast
- stripe(a);
- stripe(b);
- if (a.empty() || (a.size() == 1 && a[0] == 0)) {
- return {{}, {}};
- }
- if (2 * n < 18) {
- ll A = 0, B = 0;
- for (int i = a.size() - 1; i >= 0; --i) {
- A *= 10;
- A += a[i];
- }
- for (int i = b.size() - 1; i >= 0; --i) {
- B *= 10;
- B += b[i];
- }
- return {to_num(A / B), to_num(A % B)};
- }
- vector<int> a1;
- for (int i = n/2; i < a.size(); ++i) {
- a1.push_back(a[i]);
- }
- // a = ... a1
- auto [del1, ost1] = div32(a1, b, n / 2);
- a.resize(n/2 + ost1.size());
- for (int i = 0; i < ost1.size(); ++i) {
- a[i + n / 2] = ost1[i];
- }
- auto [del2, ost2] = div32(a, b, n / 2);
- del2.resize(n / 2 + del1.size());
- for (int i = 0; i < del1.size(); ++i) {
- del2[n / 2 + i] = del1[i];
- }
- return {del2, ost2};
- }
- bool minus_(vector<int>& a, vector<int> b) { // true if plus
- stripe(a);
- stripe(b);
- if (greater_(a, b) || equal(a.begin(), a.end(), b.begin(), b.end())) {
- bool f = false;
- for (int i = 0; i < b.size(); ++i) {
- a[i] -= b[i] + f;
- if (a[i] < 0) {
- a[i] += 10;
- f = true;
- } else {
- f = false;
- }
- }
- int j = b.size();
- while (f && j < a.size()) {
- a[j] -= f;
- if (a[j] < 0) {
- a[j] += 10;
- f = true;
- } else {
- f = false;
- }
- j++;
- }
- return true;
- } else {
- bool f = false;
- swap(a, b);
- for (int i = 0; i < b.size(); ++i) {
- a[i] -= b[i] + f;
- if (a[i] < 0) {
- a[i] += 10;
- f = true;
- } else {
- f = false;
- }
- }
- int j = b.size();
- while (f && j < a.size()) {
- a[j] -= f;
- if (a[j] < 0) {
- a[j] += 10;
- f = true;
- } else {
- f = false;
- }
- j++;
- }
- return false;
- }
- }
- bool plus_(vector<int>& a, vector<int> b) { // -a + b
- stripe(a);
- stripe(b);
- bool f = minus_(b, a);
- swap(a, b);
- return f;
- }
- void dec_(vector<int>& a) { // a--
- for (int i = 0; i < a.size(); ++i) {
- if (a[i] == 0) {
- a[i] = 9;
- } else {
- --a[i];
- break;
- }
- }
- while (a.size() > 1 && a.back() == 0) {
- a.pop_back();
- }
- }
- void inc_(vector<int>& a) { // a++
- int carry = 1;
- for (int & i : a) {
- i += carry;
- if (i >= 10) {
- carry = 1;
- i -= 10;
- } else {
- carry = 0;
- break;
- }
- }
- if (carry) {
- a.push_back(1);
- }
- }
- vector<int> subl(const vector<int>& A) { // a * 2
- vector<int> a = A;
- int carry = 0;
- for (int & i : a) {
- i += carry;
- i *= 2;
- if (i >= 10) {
- carry = 1;
- i -= 10;
- } else {
- carry = 0;
- }
- }
- if (carry) {
- a.push_back(1);
- }
- return a;
- }
- pair<vector<int>, vector<int>> div32(vector<int> a, vector<int> b, int n) {
- stripe(a);
- stripe(b);
- if (a.empty() || (a.size() == 1 && a[0] == 0)) {
- return {{}, {}};
- }
- if (3 * n < 18) {
- ll A = 0, B = 0;
- for (int i = a.size() - 1; i >= 0; --i) {
- A *= 10;
- A += a[i];
- }
- for (int i = b.size() - 1; i >= 0; --i) {
- B *= 10;
- B += b[i];
- }
- return {to_num(A / B), to_num(A % B)};
- }
- if (a.size() <= 2 * n && b.size() <= n) {
- return div21(a, b, n);
- }
- assert(b.size() > n);
- vector<int> b1;
- for (int i = b.size() - n; i < b.size(); ++i) {
- b1.push_back(b[i]);
- }
- vector<int> a1;
- for (int i = b.size() - n; i < a.size(); ++i) {
- a1.push_back(a[i]);
- }
- vector<int> b2;
- for (int i = 0; i < n; ++i){
- b2.push_back(0);
- }
- for (auto i : b1) {
- b2.push_back(i);
- }
- vector<int> del1, ost1;
- if (greater_(a1, b2)) {
- // b1 * 2 и все будет ок
- // auto ii = div21(a1, subl(b1), n);
- // del1 = subl(ii.first);
- // ost1 = subl(ii.second);
- // bool f = minus_(ost1, b);
- // while (f) {
- // inc_(del1);
- // f = minus_(ost1, b);
- // }
- for (int i = 0; i < n; ++i) {
- del1.push_back(9);
- }
- } else {
- auto ii = div21(a1, b1, n);
- del1 = ii.first;
- ost1 = ii.second;
- }
- bool f = minus_(a, mulFFT(b, del1));
- while (!f) {
- f = plus_(a, b);
- dec_(del1);
- }
- return {del1, a};
- }
- void solve() {
- initFFT();
- string a, b;
- cin >> a >> b;
- if (a.length() < b.length()) {
- cout << 0 << endl;
- return;
- }
- vector<int> first_num = to_num(a);
- vector<int> second_num = to_num(b);
- if (greater_(second_num, first_num)) {
- cout << 0 << endl;
- return;
- }
- int n = make2(int(a.size()));
- auto [r1, r2] = div21(first_num, second_num, n);
- stripe(r1);
- for (int i = r1.size() - 1; i >= 0; --i) {
- cout << r1[i];
- }
- cout << endl;
- }
- int32_t main() {
- ios_base::sync_with_stdio(false);
- cin.tie(NULL);
- cout.tie(NULL);
- cout.precision(30);
- int testCases = 1;
- #ifdef LOCAL
- freopen("input.txt", "r", stdin);
- //freopen("output.txt", "w", stdout);
- cin >> testCases;
- #else
- //freopen("inputik.txt", "r", stdin);
- //freopen("outputik.txt", "w", stdout);
- testCases = 1;
- #endif
- while (testCases--) {
- solve();
- #ifdef LOCAL
- cout << "__________________________" << endl;
- #endif
- }
- #ifdef LOCAL
- cerr << endl << "finished in " << clock() * 1.0 / CLOCKS_PER_SEC << " sec" << endl;
- #endif
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement