Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <cstdio>
- #include <cstring>
- #include <algorithm>
- #include <iostream>
- #include <complex>
- #include <string>
- #include <vector>
- #define LOG(FMT...) fprintf(stderr, FMT)
- #define DECL_IOSTREAM(T) istream& operator>>(istream& is, T& x) { \
- string s; \
- is >> s; \
- x = s; \
- return is; \
- } \
- ostream& operator<<(ostream& os, const T& x) { \
- return os << x.toString(); \
- }
- using namespace std;
- typedef long long ll;
- typedef complex<double> cd;
- const int BASE = 5, MOD = 100000, LGM = 17;
- const double PI = 3.1415926535897932384626;
- class UnsignedDigit;
- namespace DivHelper { UnsignedDigit quasiInv(const UnsignedDigit& v); }
- class UnsignedDigit {
- private:
- vector<int> digits;
- public:
- UnsignedDigit() : digits(1) {}
- UnsignedDigit(const vector<int>& digits);
- UnsignedDigit(ll x);
- UnsignedDigit(string str);
- int size() const { return digits.size(); }
- bool zero() const { return digits.size() == 1 && digits[0] == 0; }
- bool operator<(const UnsignedDigit& rhs) const;
- bool operator<=(const UnsignedDigit& rhs) const;
- bool operator==(const UnsignedDigit& rhs) const;
- UnsignedDigit operator+(const UnsignedDigit& rhs) const;
- UnsignedDigit operator-(const UnsignedDigit& rhs) const;
- UnsignedDigit operator*(const UnsignedDigit& rhs) const;
- UnsignedDigit operator/(const UnsignedDigit& rhs) const;
- UnsignedDigit operator%(const UnsignedDigit& rhs) const;
- UnsignedDigit operator/(int v) const;
- UnsignedDigit move(int k) const;
- string toString() const;
- friend UnsignedDigit powrt(const UnsignedDigit& x, int m);
- friend UnsignedDigit DivHelper::quasiInv(const UnsignedDigit& v);
- friend void swap(UnsignedDigit& lhs, UnsignedDigit& rhs) { swap(lhs.digits, rhs.digits); }
- private:
- void trim();
- };
- class UnsignedDecimal {
- private:
- UnsignedDigit value;
- int exponent;
- public:
- UnsignedDecimal() : value(), exponent() {}
- UnsignedDecimal(const UnsignedDigit& value, int exponent = 0) : value(value), exponent(exponent) {}
- UnsignedDecimal(string str);
- bool operator<(const UnsignedDecimal& rhs) const;
- bool operator<=(const UnsignedDecimal& rhs) const;
- bool operator==(const UnsignedDecimal& rhs) const;
- UnsignedDecimal operator+(const UnsignedDecimal& rhs) const;
- UnsignedDecimal operator-(const UnsignedDecimal& rhs) const;
- UnsignedDecimal operator*(const UnsignedDecimal& rhs) const;
- string toString() const;
- };
- class Int {
- private:
- UnsignedDigit value;
- int sign;
- Int(const UnsignedDigit& value, int sign) : value(value), sign(sign) {}
- public:
- Int() : value(), sign() {}
- Int(ll x) : value(x < 0 ? -x : x), sign(x == 0 ? 0 : x < 0 ? -1 : 1) {}
- Int(const UnsignedDigit& value) : value(value), sign(!value.zero()) {}
- Int(const string& str);
- bool operator<(const Int& rhs) const;
- bool operator<=(const Int& rhs) const { return !(rhs < *this); }
- bool operator>(const Int& rhs) const { return rhs < *this; }
- bool operator>=(const Int& rhs) const { return !(*this < rhs); }
- bool operator==(const Int& rhs) const { return sign == rhs.sign && value == rhs.value; }
- bool operator!=(const Int& rhs) const { return !(*this == rhs); }
- Int operator-() const { return Int(value, -sign); }
- Int operator+(const Int& rhs) const;
- Int operator-(const Int& rhs) { return *this + -rhs; }
- Int operator*(const Int& rhs) { return Int(value * rhs.value, sign * rhs.sign); }
- Int operator/(const Int& rhs) { return Int(value / rhs.value, sign * rhs.sign); }
- string toString() const;
- };
- class Decimal {};
- namespace ConvHelper {
- void fft(cd* a, int lgn, int d) {
- int n = 1 << lgn;
- {
- static vector<int> brev;
- if (n != brev.size()) {
- brev.resize(n);
- for (int i = 0; i < n; ++i)
- brev[i] = (brev[i >> 1] >> 1) | ((i & 1) << (lgn - 1));
- }
- for (int i = 0; i < n; ++i)
- if (brev[i] < i)
- swap(a[brev[i]], a[i]);
- }
- for (int t = 1; t < n; t <<= 1) {
- cd omega(cos(PI / t), sin(PI * d / t));
- for (int i = 0; i < n; i += t << 1) {
- cd* p = a + i;
- cd w(1);
- for (int j = 0; j < t; ++j) {
- cd x = p[j + t] * w;
- p[j + t] = p[j] - x;
- p[j] += x;
- w *= omega;
- }
- }
- }
- if (d == -1) {
- for (int i = 0; i < n; ++i)
- a[i] /= n;
- }
- }
- vector<ll> conv(const vector<int>& a, const vector<int>& b) {
- int n = a.size() - 1, m = b.size() - 1;
- if (n < 1000 / (m + 1) || n < 10 || m < 10) {
- vector<ll> ret(n + m + 1);
- for (int i = 0; i <= n; ++i)
- for (int j = 0; j <= m; ++j)
- ret[i + j] += a[i] * (ll)b[j];
- return ret;
- }
- int lgn = 0;
- while ((1 << lgn) <= n + m)
- ++lgn;
- vector<cd> ta(a.begin(), a.end()), tb(b.begin(), b.end());
- ta.resize(1 << lgn);
- tb.resize(1 << lgn);
- fft(ta.begin().base(), lgn, 1);
- fft(tb.begin().base(), lgn, 1);
- for (int i = 0; i < (1 << lgn); ++i)
- ta[i] *= tb[i];
- fft(ta.begin().base(), lgn, -1);
- vector<ll> ret(n + m + 1);
- for (int i = 0; i <= n + m; ++i)
- ret[i] = ta[i].real() + 0.5;
- return ret;
- }
- }
- namespace DivHelper {
- UnsignedDigit quasiInv(const UnsignedDigit& v) {
- if (v.digits.size() == 1) {
- UnsignedDigit tmp;
- tmp.digits.resize(3);
- tmp.digits[2] = 1;
- return tmp / v.digits[0];
- }
- if (v.digits.size() == 2) {
- UnsignedDigit sum = 0, go = 1;
- vector<int> tmp(4);
- go = go.move(4);
- vector<UnsignedDigit> db(LGM);
- db[0] = v;
- for (int i = 1; i < LGM; ++i)
- db[i] = db[i - 1] + db[i - 1];
- for (int i = 3; i >= 0; --i) {
- for (int k = LGM - 1; k >= 0; --k)
- if (sum + db[k].move(i) <= go) {
- sum = sum + db[k].move(i);
- tmp[i] |= 1 << k;
- }
- }
- return tmp;
- }
- int n = v.digits.size(), k = (n + 2) / 2;
- UnsignedDigit tmp = quasiInv(vector<int>(v.digits.end().base() - k, v.digits.end().base()));
- return (UnsignedDigit(2) * tmp).move(n - k) - (v * tmp * tmp).move(-2 * k);
- }
- }
- UnsignedDigit::UnsignedDigit(ll x) {
- while (x) {
- digits.push_back(x % MOD);
- x /= MOD;
- }
- if (digits.empty())
- digits.push_back(0);
- }
- UnsignedDigit UnsignedDigit::move(int k) const {
- if (k == 0)
- return *this;
- if (k < 0) {
- if (-k >= digits.size())
- return UnsignedDigit();
- return vector<int>(digits.begin().base() + (-k), digits.end().base());
- }
- if (digits.size() == 1 && digits[0] == 0)
- return UnsignedDigit();
- UnsignedDigit ret;
- ret.digits.resize(k, 0);
- ret.digits.insert(ret.digits.end(), digits.begin(), digits.end());
- return ret;
- }
- bool UnsignedDigit::operator<(const UnsignedDigit& rhs) const {
- int n = digits.size(), m = rhs.digits.size();
- if (n != m)
- return n < m;
- for (int i = n - 1; i >= 0; --i)
- if (digits[i] != rhs.digits[i])
- return digits[i] < rhs.digits[i];
- return false;
- }
- bool UnsignedDigit::operator<=(const UnsignedDigit& rhs) const {
- int n = digits.size(), m = rhs.digits.size();
- if (n != m)
- return n < m;
- for (int i = n - 1; i >= 0; --i)
- if (digits[i] != rhs.digits[i])
- return digits[i] < rhs.digits[i];
- return true;
- }
- bool UnsignedDigit::operator==(const UnsignedDigit& rhs) const {
- int n = digits.size(), m = rhs.digits.size();
- if (n != m)
- return false;
- return memcmp(digits.begin().base(), rhs.digits.begin().base(), n * sizeof(int)) == 0;
- }
- UnsignedDigit UnsignedDigit::operator+(const UnsignedDigit& rhs) const {
- int n = digits.size(), m = rhs.digits.size();
- vector<int> tmp = digits;
- if (m > n) {
- tmp.resize(m + 1);
- for (int i = 0; i < m; ++i)
- if ((tmp[i] += rhs.digits[i]) >= MOD) {
- tmp[i] -= MOD;
- ++tmp[i + 1];
- }
- } else {
- tmp.resize(n + 1);
- for (int i = 0; i < m; ++i)
- if ((tmp[i] += rhs.digits[i]) >= MOD) {
- tmp[i] -= MOD;
- ++tmp[i + 1];
- }
- for (int i = m; i < n; ++i)
- if (tmp[i] == MOD) {
- tmp[i] = 0;
- ++tmp[i + 1];
- }
- }
- return tmp;
- }
- UnsignedDigit UnsignedDigit::operator*(const UnsignedDigit& rhs) const {
- vector<ll> tmp = ConvHelper::conv(digits, rhs.digits);
- for (int i = 0; i + 1 < tmp.size(); ++i) {
- tmp[i + 1] += tmp[i] / MOD;
- tmp[i] %= MOD;
- }
- while (tmp.back() >= MOD) {
- ll remain = tmp.back() / MOD;
- tmp.back() %= MOD;
- tmp.push_back(remain);
- }
- return vector<int>(tmp.begin(), tmp.end());
- }
- UnsignedDigit UnsignedDigit::operator/(const UnsignedDigit& rhs) const {
- int m = digits.size(), n = rhs.digits.size(), t = 0;
- if (m < n)
- return 0;
- if (m > n * 2)
- t = m - 2 * n;
- UnsignedDigit sv = DivHelper::quasiInv(rhs.move(t));
- UnsignedDigit ret = move(t) * sv;
- ret = ret.move(-2 * (n + t));
- if ((ret + 1) * rhs <= *this)
- ret = ret + 1;
- return ret;
- }
- UnsignedDigit UnsignedDigit::operator%(const UnsignedDigit &rhs) const {
- if (digits.size() < rhs.digits.size())
- return *this;
- return (*this - ((*this / rhs) * rhs));
- }
- UnsignedDigit UnsignedDigit::operator/(int k) const {
- UnsignedDigit ret;
- int n = digits.size();
- ret.digits.resize(n);
- ll r = 0;
- for (int i = n - 1; i >= 0; --i) {
- r = r * MOD + digits[i];
- ret.digits[i] = r / k;
- r %= k;
- }
- ret.trim();
- return ret;
- }
- UnsignedDigit UnsignedDigit::operator-(const UnsignedDigit& rhs) const {
- UnsignedDigit ret(*this);
- int n = rhs.digits.size();
- for (int i = 0; i < n; ++i)
- if ((ret.digits[i] -= rhs.digits[i]) < 0) {
- ret.digits[i] += MOD;
- --ret.digits[i + 1];
- }
- ret.trim();
- return ret;
- }
- UnsignedDigit::UnsignedDigit(const vector<int>& digits) : digits(digits) {
- if (this->digits.empty())
- this->digits.resize(1);
- trim();
- }
- void UnsignedDigit::trim() {
- while (digits.size() > 1 && digits.back() == 0)
- digits.pop_back();
- }
- string UnsignedDigit::toString() const {
- static char buf[BASE + 1];
- sprintf(buf, "%d", digits.back());
- string ret = buf;
- int q = ret.size();
- ret.resize(q + BASE * (digits.size() - 1));
- int j = 0;
- for (int i = (int)digits.size() - 2; i >= 0; --i) {
- sprintf(const_cast<char*>(ret.c_str()) + q + j * BASE, "%05d", digits[i]);
- ++j;
- }
- return ret;
- }
- UnsignedDigit::UnsignedDigit(string str) {
- reverse(str.begin(), str.end());
- digits.resize((str.size() + BASE - 1) / BASE);
- int cur = 1;
- for (int i = 0; i < str.size(); ++i) {
- if (i % BASE == 0)
- cur = 1;
- digits[i / BASE] += cur * (str[i] - '0');
- cur *= 10;
- }
- trim();
- }
- UnsignedDigit pow(UnsignedDigit x, int k) {
- UnsignedDigit ret = 1;
- while (k) {
- if (k & 1)
- ret = ret * x;
- if (k >>= 1)
- x = x * x;
- }
- return ret;
- }
- DECL_IOSTREAM(UnsignedDigit)
- DECL_IOSTREAM(UnsignedDecimal)
- DECL_IOSTREAM(Int)
- Int::Int(const string& str) : sign(1) {
- if (str[0] == '-') {
- sign = -1;
- value = UnsignedDigit(string(str.begin() + 1, str.end()));
- } else
- value = UnsignedDigit(str);
- if (value.zero())
- sign = 0;
- }
- string Int::toString() const {
- if (sign < 0)
- return "-" + value.toString();
- return value.toString();
- }
- Int Int::operator+(const Int& rhs) const {
- if (sign == 0)
- return rhs;
- if (rhs.sign == 0)
- return *this;
- if (sign == rhs.sign)
- return Int(value + rhs.value, sign);
- if (value == rhs.value)
- return Int();
- if (rhs.value < value)
- return Int(value - rhs.value, sign);
- return Int(rhs.value - value, rhs.sign);
- }
- UnsignedDigit powrt(const UnsignedDigit& x, int m) {
- if (x.size() <= m) {
- int l = 0, r = MOD - 1;
- while (l < r) {
- int mid = (l + r + 1) >> 1;
- if (pow(UnsignedDigit(mid), m) <= x)
- l = mid;
- else
- r = mid - 1;
- }
- return l;
- }
- if (x.size() <= m * 2) {
- UnsignedDigit ret;
- ret.digits.resize(2);
- int l = 0, r = MOD - 1;
- while (l < r) {
- int mid = (l + r + 1) >> 1;
- ret.digits[1] = mid;
- if (pow(ret, m) <= x)
- l = mid;
- else
- r = mid - 1;
- }
- ret.digits[1] = l;
- l = 0;
- r = MOD - 1;
- while (l < r) {
- int mid = (l + r + 1) >> 1;
- ret.digits[0] = mid;
- if (pow(ret, m) <= x)
- l = mid;
- else
- r = mid - 1;
- }
- ret.digits[0] = l;
- return ret;
- }
- int n = x.size(), take = n / m / 2;
- UnsignedDigit sub((powrt(x.move(-take * m), m) + 1).move(take));
- UnsignedDigit ret = (sub * (m - 1) + x / pow(sub, m - 1)) / m;
- int l = max(ret.digits[0] - 10, 0), r = min(ret.digits[0] + 10, MOD - 1);
- while (l < r) {
- int mid = (l + r + 1) >> 1;
- ret.digits[0] = mid;
- if (pow(ret, m) <= x)
- l = mid;
- else
- r = mid - 1;
- }
- ret.digits[0] = l;
- return ret;
- }
- UnsignedDecimal::UnsignedDecimal(string str) : exponent() {
- int k = str.size() - 1;
- while (str[k] == '0' && k)
- --k;
- str.erase(k + 1);
- unsigned pos = str.find('.');
- if (pos == str.npos) {
- value = UnsignedDigit(str);
- exponent = str.size() - k - 1;
- } else {
- exponent = -int(str.length() - pos - 1);
- value = str.substr(0, pos) + str.substr(pos + 1);
- }
- }
- string UnsignedDecimal::toString() const {
- string gen(value.toString());
- if (exponent > 0) {
- gen.insert(gen.end(), exponent, '0');
- } else if (exponent < 0) {
- if (-exponent >= gen.size())
- gen.insert(0, -exponent - gen.size() + 1, '0');
- gen.insert(gen.end() + exponent, '.');
- }
- return gen;
- }
- UnsignedDecimal UnsignedDecimal::operator*(const UnsignedDecimal& rhs) const {
- return UnsignedDecimal(value * rhs.value, exponent + rhs.exponent);
- }
- UnsignedDecimal pow(UnsignedDecimal v, int k) {
- UnsignedDecimal ret(1, 0);
- while (k) {
- if (k & 1)
- ret = ret * v;
- if (k >>= 1)
- v = v * v;
- }
- return ret;
- }
- #include <cstdio>
- #include <cmath>
- #include <ctime>
- #include <cstring>
- #include <cstdlib>
- #include <algorithm>
- #include <numeric>
- #include <limits>
- #include <functional>
- #include <stack>
- #include <vector>
- #include <set>
- #include <map>
- #include <queue>
- #define LOG(FMT...) fprintf(stderr, FMT)
- using namespace std;
- typedef long long ll;
- typedef unsigned long long ull;
- UnsignedDecimal tst;
- int main() {
- #ifdef LBT
- freopen("test.in", "r", stdin);
- int nol_cl = clock();
- #endif
- string str;
- int k;
- while (cin >> str >> k) {
- tst = str;
- str = pow(tst, k).toString();
- if (str[0] == '0')
- str.erase(0, 1);
- cout << str << endl;
- }
- #ifdef LBT
- LOG("Time: %dms\n", int((clock() - nol_cl) / (double)CLOCKS_PER_SEC * 1000));
- #endif
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment