結果

問題 No.2781 A%B問題
コンテスト
ユーザー T101010101
提出日時 2025-12-03 10:08:41
言語 C++23
(gcc 13.3.0 + boost 1.89.0)
結果
AC  
実行時間 3 ms / 2,000 ms
コード長 37,127 bytes
記録
記録タグの例:
初AC ショートコード 純ショートコード 純主流ショートコード 最速実行時間
コンパイル時間 5,468 ms
コンパイル使用メモリ 354,672 KB
実行使用メモリ 7,848 KB
最終ジャッジ日時 2025-12-03 10:08:47
合計ジャッジ時間 6,184 ms
ジャッジサーバーID
(参考情報)
judge5 / judge3
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
other AC * 20
権限があれば一括ダウンロードができます

ソースコード

diff #
raw source code

/* #region */
#ifdef ONLINE_JUDGE
    #define NDEBUG
    #pragma GCC optimize("O3,unroll-loops")
    #ifdef ATCODER
        #pragma GCC target("sse,sse2,sse3,ssse3,fma,abm,mmx,bmi,bmi2,popcnt,lzcnt")
        #pragma GCC target("avx2") // NG : CF, CodeChef, HamakoOJ
    #endif
#endif

#include <bits/extc++.h>

// #include <atcoder/all>
#if __has_include(<atcoder/segtree.hpp>)
    #include <atcoder/segtree.hpp>
    #include <atcoder/lazysegtree.hpp>
    using namespace atcoder;
#endif

#ifdef ATCODER
    #include <boost/unordered/unordered_flat_map.hpp>
    #define unordered_map boost::unordered_flat_map
    #include <boost/unordered/unordered_flat_set.hpp>
    #define unordered_set boost::unordered_flat_set
    #if __has_include(<absl/container/btree_map.h>)
        #include <absl/container/btree_map.h>
        #define map absl::btree_map
    #endif
#endif

// #include <boost/multiprecision/cpp_dec_float.hpp>
// #include <boost/multiprecision/cpp_int.hpp>
// namespace mp = boost::multiprecision;
// using lll = mp::cpp_int;
// using lld = mp::cpp_dec_float_50; // 十進50桁. ldは19桁.
// // using lld = mp::cpp_dec_float_100;
// // using lld = mp::number<mp::cpp_dec_float<200>>;
// constexpr lld Beps = 0.00000000000000000000000000000001; // 1e-32
// constexpr bool equals(lld a, lld b) { return mp::fabs(a - b) < Beps; }

inline namespace define {
    using namespace std;
    using namespace __gnu_pbds;

    #define int ll
    #define endl '\n'

    using ll = int64_t;
    using ld = long double;
    using ull = uint64_t;
    using i128 = __int128_t;

    constexpr ld PI = acosl(-1);
    constexpr ld EPS = 1e-10;
    constexpr int INF = 1 << 30;
    constexpr ll INFL = 1LL << 61;
    constexpr int MOD = 998244353;
    // constexpr int MOD = 1000000007;

    constexpr int e4 = 100'00, e5 = 100'000, e6 = 100'000'0, e7 = 100'000'00, e8 = 100'000'000, e9 = 100'000'000'0;
    constexpr ll e10 = 100'000'000'00LL, e11 = 100'000'000'000LL, e12 = 100'000'000'000'0LL, e13 = 100'000'000'000'00LL, e14 = 100'000'000'000'000LL, e15 = 100'000'000'000'000'0LL, e16 = 100'000'000'000'000'00LL, e17 = 100'000'000'000'000'000LL, e18 = 100'000'000'000'000'000'0LL;
    constexpr ull e19 = 100'000'000'000'000'000'00uLL;

    constexpr array<int32_t, 9> dx = {0, 1, 0, -1, 1, 1, -1, -1, 0}; // → ↓ ← ↑ ↘ ↙ ↖ ↗ 自
    constexpr array<int32_t, 9> dy = {1, 0, -1, 0, 1, -1, -1, 1, 0};
}

inline namespace util {
    constexpr bool equals(ld a, ld b) noexcept { return fabs((a) - (b)) < EPS; }

    constexpr bool add_overflow(integral auto a, integral auto b) noexcept {
        return __builtin_add_overflow_p(a, b, decltype(a + b){});
    }
    constexpr bool sub_overflow(integral auto a, integral auto b) noexcept {
        return __builtin_sub_overflow_p(a, b, decltype(a + b){});
    }
    constexpr bool mul_overflow(integral auto a, integral auto b) noexcept {
        return __builtin_mul_overflow_p(a, b, decltype(a + b){});
    }
    template <typename T> constexpr bool shift_overflow(T a, int k) noexcept {
        assert(a >= 0);
        if (a == 0) return false;
        if (k > 64 or k < 0) return true;
        if (((__int128_t)a << k) > numeric_limits<T>::max()) return true;
        return false;
    }

    template <typename T> constexpr auto POW(T x, int n) noexcept {
        assert(n >= 0 && is_integral_v<T>);
        using U = conditional_t<is_same_v<T, int32_t>, int64_t, T>; // i32ならi64まで拡張
        U x_ = x, ret = 1;
        while (n) {
            if (n & 1) ret *= x_;
            if (n == 1) break;
            assert(!mul_overflow(x_, x_));
            x_ *= x_;
            n >>= 1;
        }
        return ret;
    }
    template <typename T> constexpr bool pow_overflow(T x, int n) noexcept {
        assert(is_integral_v<T>);
        assert(!(is_same_v<T, int32_t>)); // i32での判定が想定通りの挙動ならこの行をコメントアウト
        T ret = 1;
        while (n > 0) {
            if (n & 1) {
                if (mul_overflow(ret, x)) return true;
                ret *= x;
            }
            if (n == 1) break;
            if (mul_overflow(x, x)) return true;
            x *= x;
            n >>= 1;
        }
        return false;
    }

    constexpr auto per(integral auto x, integral auto y) noexcept { // x = qy + r (0 <= r < y) を満たすq
        assert(y != 0);
        if (x >= 0 && y > 0) return x / y;
        if (x >= 0 && y < 0) return x / y;
        if (x < 0 && y < 0) return x / y + (x % y < 0);
        return x / y - (x % y < 0); //  (x < 0 && y > 0)
    }
    constexpr auto mod(integral auto x, integral auto y) noexcept { // x = qy + r (0 <= r < y) を満たすr
        assert(y != 0);
        return x - y * per(x, y);
    } // https://yukicoder.me/problems/no/2781
    constexpr auto floor(integral auto x, integral auto y) noexcept { // (ld)x / y 以下の最大の整数
        assert(y != 0);
        if (y < 0) x = -x, y = -y;
        return x >= 0 ? x / y : (x + 1) / y - 1;
    }
    constexpr auto ceil(integral auto x, integral auto y) noexcept { // (ld)x / y 以上の最小の整数
        assert(y != 0);
        if (y < 0) x = -x, y = -y;
        return x > 0 ? (x - 1) / y + 1 : x / y;
    }
    constexpr auto round(integral auto x, integral auto y) noexcept { // (ld)x / y を小数第1位について四捨五入
        assert(y != 0);
        if (x*y < 0) return -((abs(x) * 2 + abs(y)) / (abs(y) * 2));
        return (x * 2 + y) / (y * 2);
    } // https://www.acmicpc.net/problem/2108
    constexpr auto round(integral auto x, integral auto y, int k) noexcept { // (ld)x / y を10^kの位に関して四捨五入
        assert(y != 0 && k >= 0);
        if (k == 0) return (x * 2 + y) / (y * 2);
        x /= y * POW(10, k - 1);
        if (x % 10 >= 5) return (x + 10 - x % 10) * POW(10, k - 1);
        return x * POW(10, k - 1);
    }
    constexpr auto round2(integral auto x, integral auto y) noexcept { // 五捨五超入 // 未verify
        assert(y != 0);
        if (y < 0) y = -y, x = -x;
        auto z = x / y;
        if ((z * 2 + 1) * y <= y * 2) z++;
        return z;
    }
    constexpr int floor(ld x) noexcept { // 未.  負数でも小さい方に丸める
        if (x > -EPS) return (int)(floorl(x + EPS) + EPS);
        return -(int)((ceill(-x - EPS)) + EPS);
    }
    constexpr int ceil(ld x) noexcept { // 未.  負数でも大きい方に丸める
        if (x > EPS) return (int)(ceill(x - EPS) + EPS);
        return -(int)((floorl(-x + EPS)) + EPS);
    }
    constexpr int round(ld x) noexcept { // 未. 負数でも.5の場合は大きい方に丸める
        if (x > EPS) return (int)(roundl(x + EPS) + EPS);
        return (int)(roundl(x + EPS) - EPS);
    }
    // constexpr int get(ld x, int k) noexcept { // 未. xの10^kの位の桁
    // }
    constexpr ld floor(ld x, int k) noexcept { // xを10^kの位に関してflooring
        assert(!pow_overflow(10, -k));
        ld d = pow(10, -k);
        return floor(x * d) / d; // 未verify
    }
    constexpr ld ceil(ld x, int k) noexcept { // xを10^kの位に関してceiling
        assert(!pow_overflow(10, -k));
        ld d = pow(10, -k);
        return ceil(x * d) / d; // 未verify
    }
    constexpr ld round(ld x, int k) noexcept { // xを10^kの位に関して四捨五入.
        assert(!pow_overflow(10, -k));
        ld d = pow(10, -k);
        return round(x * d) / d;
    }
    // constexpr int kth(int x, int y, int k) noexcept { // x / yの10^kの位の桁
    // }
    constexpr int floor(ld x, ld y) noexcept { // 誤差対策TODO
        assert(!equals(y, 0));
        return floorl(x / y);
        // floor(x) = ceil(x - 1) という話も
    }
    constexpr int ceil(ld x, ld y) noexcept { // 誤差対策TODO // ceil(p/q) = -floor(-(p/q))らしい
        assert(!equals(y, 0));
        return ceill(x / y);
        // ceil(x) = floor(x + 1)
    }
    constexpr int perl(ld x, ld y) noexcept { // x = qy + r (0 <= r < y, qは整数) を満たす q
        // 未verify. 誤差対策TODO. EPS外してもいいかも
        assert(!equals(y, 0));
        if (x >= 0 && y > 0) return floorl(x / y) + EPS;
        if (x >= 0 && y < 0) return -floorl(x / fabs(y));
        if (x < 0 && y < 0) return floorl(x / y) + (x - floorl(x/y)*y < -EPS);
        return floorl(x / y) - (x - floorl(x/y)*y < -EPS); //  (x < 0 && y > 0)
    }
    constexpr ld modl(ld x, ld y) noexcept { // x = qy + r (0 <= r < y, qは整数) を満たす r
        // 未verify. 誤差対策TODO. -0.0が返りうる
        assert(!equals(y, 0));
        if (x >= 0) return x - fabs(y)*fabs(perl(x, y));
        return x - fabs(y)*floor(x, fabs(y));
    }
    constexpr int seisuu(ld x) noexcept { return (int)x; } // 整数部分. 誤差対策TODO
    constexpr int modf(ld x) noexcept {
        if (x < 0) return ceil(x);
        else return floor(x);
    }
    // 正なら+EPS, 負なら-EPSしてから、文字列に直して小数点以下を捨てる?
    constexpr int seisuu(int x, int y) noexcept {
        assert(y != 0);
        return x / y;
    }
    constexpr int seisuu(ld x, ld y) noexcept { // 誤差対策TODO
        assert(!equals(y, 0));
        return (int)(x / y);
    }

    constexpr int floor_log(int base, int x) noexcept { // log_base{x} のfloor
        assert(base >= 2);
        int ret = 0, now = 1;
        while (now <= x) {
            now *= base;
            if (now <= x) ret++;
        }
        return ret;
    }
    constexpr int ceil_log(int base, int x) noexcept { // log_base{x} のceil
        assert(base >= 2);
        int ret = 0, now = 1;
        while (now < x) {
            now *= base;
            ret++;
        }
        return ret;
    }

    constexpr auto max(const auto &a, const auto &b) noexcept {
        if (a.first > b.first or a.first == b.first && a.second > b.second) return a;
        return b;
    }
    constexpr auto min(const auto &a, const auto &b) noexcept {
        if (a.first < b.first or a.first == b.first && a.second < b.second) return a;
        return b;
    }

    template <typename T> constexpr bool chmax(T &a, const T &b) noexcept {
        if (a < b) { a = b; return true; } return false;
    }
    template <typename T> constexpr bool chmin(T &a, const T &b) noexcept {
        if (a > b) { a = b; return true; } return false;
    }
    template <typename T, typename U> constexpr bool chmax(pair<T, U> &a, const pair<T, U> &b) noexcept {
        if (a.first < b.first or a.first == b.first && a.second < b.second) { a = b; return true; }
        return false;
    }
    template <typename T, typename U> constexpr bool chmin(pair<T, U> &a, const pair<T, U> &b) noexcept {
        if (a.first > b.first or a.first == b.first && a.second > b.second) { a = b; return true; }
        return false;
    }
    template <typename T> constexpr T mid(T a, T b, T c) noexcept {
        return max(min(a, b), min(max(a, b), c));
    }

    template <typename T, typename... Args>
    constexpr void Sort(T& a, T& b, Args&... args) noexcept {
        vector<T> vec = {a, b, args...};
        sort(vec.begin(), vec.end());
        auto it = vec.begin();
        a = *it++; b = *it++;
        int dummy[] = {0, (args = *it++, 0)...};
        static_cast<void>(dummy);
    }
    template <typename T, typename... Args>
    constexpr void Sortr(T& a, T& b, Args&... args) noexcept {
        vector<T> vec = {a, b, args...};
        sort(vec.rbegin(), vec.rend());
        auto it = vec.begin();
        a = *it++; b = *it++;
        int dummy[] = {0, (args = *it++, 0)...};
        static_cast<void>(dummy);
    }

    template <typename T, typename U>
    constexpr void sort(vector<T> &A, vector<U> &B) noexcept {
        vector<pair<T, U>> P(A.size());
        for (int i = 0; i < (int)A.size(); i++) P[i] = {A[i], B[i]};
        sort(P.begin(), P.end());
        for (int i = 0; i < (int)A.size(); i++) A[i] = P[i].first, B[i] = P[i].second;
    } // Aをキーにして {A[i], B[i]} をソート

    istream &operator >>(istream &is, __int128_t& x) noexcept {
        string S; is >> S;
        __int128_t ret = 0;
        bool neg = false;
        if (S[0] == '-') neg = true;
        for (int i = neg; i < (int)S.size(); i++) {
            ret = ret * 10 + S[i] - '0';
        }
        x = neg ? -ret : ret;
        return is;
    }
    ostream &operator <<(ostream &os, __int128_t x) noexcept {
        ostream::sentry s(os);
        if (s) {
            __uint128_t tmp = x < 0 ? -x : x;
            char buffer[128]; char *d = end(buffer);
            do {
                --d; *d = "0123456789"[tmp % 10]; tmp /= 10;
            } while (tmp != 0);
            if (x < 0) { --d; *d = '-'; }
            int len = end(buffer) - d;
            if (os.rdbuf()->sputn(d, len) != len) os.setstate(ios_base::badbit);
        }
        return os;
    }

    __int128_t abs(__int128_t x) noexcept {
        return x < 0 ? -x : x;
    }
    [[nodiscard]] __int128_t sto128(const string &S) noexcept {
        assert(!S.empty());
        __int128_t ret = 0;
        bool neg = false;
        if (S[0] == '-') neg = true;
        for (int i = neg; i < (int)S.size(); i++) {
            ret = ret * 10 + S[i] - '0';
        }
        return neg ? -ret : ret;
    }
    __int128_t gcd(__int128_t a, __int128_t b) noexcept {
        // a = abs(a); b = abs(b);
        return b ? gcd(b, a % b) : a;
    }
    __int128_t lcm(__int128_t a, __int128_t b) noexcept {
        if (a == 0 or b == 0) return 0;
        // a = abs(a); b = abs(b);
        return a / gcd(a, b) * b;
        // lcmが__int128_tに収まる必要あり
    }

    [[nodiscard]] string to_string(double x, int k) noexcept { // 小数第k+1を四捨五入して小数第k位までを出力
        // 切り捨てがほしい場合は to_string(x, k+1) として pop_back() すればよい?
        assert(k >= 0);
        ostringstream os;
        os << fixed << setprecision(k) << x;
        return os.str();
    }
    [[nodiscard]] string to_string(__int128_t x) noexcept {
        if (x == 0) return "0";
        string ret = "";
        bool neg = false;
        if (x < 0) { neg = true; x = -x; }
        while (x) { ret += (char)('0' + x % 10); x /= 10; }
        if (neg) ret += '-';
        reverse(ret.begin(), ret.end());
        return ret;
    }
    [[nodiscard]] string to_string(char c) noexcept { return string(1, c); }
}

inline namespace bit_util {
    using i64 = int64_t;
    // using i64 = int32_t;  // 1LLを1に直し、~llを消す。各マジックナンバーを32減らす(未verify)
    // using i64 = uint64_t; // 1LLを1uLLに直し、~llを~ullに直す. assert内の数字を1増やし、x - __builtin_clzll のxを1増やす(未verify)
    // 区間は [l, r)
    constexpr i64 lrmask(int l, int r) noexcept { assert(r < 62); return (1LL << r) - (1LL << l); }
    constexpr i64 sub_bit(i64 x, int l, int r) noexcept { assert(l < 62); return (x & ((1LL << r) - (1LL << l))) >> l; } // r溢れ可
    constexpr i64 bit_width(i64 x) noexcept { return (x == 0) ? 1 : 64 - __builtin_clzll(x); }
    constexpr i64 popcount(i64 x) noexcept { return __builtin_popcountll(x); }

    constexpr i64 popcount(i64 x, int l, int r) noexcept { return popcount(sub_bit(x, l, r)); }
    constexpr i64 unpopcount(i64 x) noexcept { return bit_width(x) - popcount(x); } // 最上位bitより下のみ
    constexpr i64 unpopcount(i64 x, int l, int r) noexcept { return r - l - popcount(sub_bit(x, l, r)); } // 最上位bitより上も含まれうる
    constexpr bool is_pow2(i64 x) noexcept { return popcount(x) == 1; }
    constexpr bool is_pow4(i64 x) noexcept { return popcount(x) == 1 && __builtin_ctzll(x) % 2 == 0; }
    constexpr int top_bit(i64 x) noexcept { return (x == 0) ? -1 : 63 - __builtin_clzll(x); }
    constexpr int bot_bit(i64 x) noexcept { return __builtin_ffsll(x) - 1; }
    constexpr i64 msb(i64 x) noexcept { return (x == 0) ? 0 : 1LL << (63 - __builtin_clzll(x)); } // mask
    constexpr i64 lsb(i64 x) noexcept { return (x & -x); } // mask
    constexpr int next_bit(i64 x, int k) noexcept {
        assert(k < 61);
        i64 mask = x & ~((1LL << (k + 1)) - 1); // k+1桁目以上のビットのみ残す
        return (mask == 0) ? -1 : __builtin_ctzll(mask);
    }
    constexpr int prev_bit(i64 x, int k) noexcept {
        assert(k < 62);
        i64 mask = x & ((1LL << k) - 1); // k桁目未満のビットのみ残す
        return (mask == 0) ? -1 : 63 - __builtin_clzll(mask);
    }
    constexpr int kth_bit(i64 x, int k) noexcept { // 下からk番目の1の位置。kは1-indexed, 位置は0-indexed
        if (popcount(x) < k) return -1;
        int pos = 0, cnt = 0;
        while (x > 0) {
            if ((x & 1) && (++cnt == k)) return pos;
            x >>= 1; pos++;
        }
    }

    constexpr int countl_zero(i64 x) noexcept { return (x == 0) ? 64 : __builtin_clzll(x); }
    constexpr int countr_zero(i64 x) noexcept { return (x == 0) ? 64 : __builtin_ctzll(x); }
    constexpr int countl_one(i64 x) noexcept { // std::countl_oneと定義が異なるので注意
        if (x == 0) return 0;
        i64 ret = 0, k = 63 - __builtin_clzll(x);
        while (k != -1 && (x & (1LL << k))) { k--; ret++; }
        return ret;
    }
    constexpr int countr_one(i64 x) noexcept { return (x == 0) ? 0 : popcount(x ^ (x & -~x)); }

    constexpr i64 l_one_mask(i64 x) noexcept { // 最上位で連なってる1のmask
        int cnt = countl_one(x);
        return (cnt == 0) ? 0 : (x & (~((1LL << (bit_width(x) - cnt)) - 1)));
    }
    constexpr i64 r_one_mask(i64 x) noexcept { // 最下位で連なってる1のmask
        int cnt = countr_one(x);
        return (cnt == 0) ? 0 : (x & ((1LL << cnt) - 1));
    }

    constexpr int floor_log2(i64 x) noexcept { assert(x > 0); return 63 - __builtin_clzll(x); } // top_bit
    constexpr int ceil_log2(i64 x) noexcept { assert(x > 0); return 64 - __builtin_clzll(x - 1); }
    constexpr i64 bit_floor(i64 x) noexcept { if (x == 0) return 0; return 1LL << (63 - __builtin_clzll(x)); } // msb
    constexpr i64 bit_ceil(i64 x) noexcept { if (x == 0) return 0; return 1LL << (64 - __builtin_clzll(x - 1)); }

    constexpr i64 rotl(i64 x, int k) noexcept { // 有効bit内でrotate. オーバーフロー注意
        i64 w = bit_width(x); k = mod(k, w);
        assert(!shift_overflow(x, k));
        return ((x << k) | (x >> (w - k))) & ((1LL << w) - 1);
    }
    constexpr i64 rotr(i64 x, int k) noexcept {
        i64 w = bit_width(x); k = mod(k, w);
        assert(!shift_overflow(x, w - k));
        return ((x >> k) | (x << (w - k))) & ((1LL << w) - 1);
    }
    constexpr i64 bit_reverse(i64 x) noexcept { // 有効bit内で左右反転
        i64 r = 0, w = bit_width(x);
        for (i64 i = 0; i < w; i++) r |= ((x >> i) & 1) << (w - i - 1);
        return r;
    }

    constexpr bool is_palindrome(i64 x) noexcept { return x == bit_reverse(x); }
    constexpr bool is_palindrome(i64 x, int l, int r) noexcept { i64 b = sub_bit(x, l, r); return b == bit_reverse(b); }
    constexpr i64 concat(i64 a, i64 b) noexcept { return (a << bit_width(b)) | b; } // オーバーフロー注意
    constexpr i64 erase(i64 x, int l, int r) noexcept { return (x >> r << l) | (x & ((1LL << l) - 1)); } // [l, r) をカット

    constexpr i64 hamming(i64 a, i64 b) noexcept { return popcount(a ^ b); }
    constexpr i64 hamming(i64 a, i64 b, int l, int r) noexcept { return popcount(sub_bit(a, l, r) ^ sub_bit(b, l, r)); }
    constexpr i64 compcount(i64 x) noexcept { return (popcount(x ^ (x >> 1)) + (x & 1)) / 2; }
    constexpr i64 compcount2(i64 x) noexcept { return compcount(x & (x >> 1)); } // 長さ2以上の連結成分の個数
    constexpr i64 adjacount(i64 x) noexcept { return popcount(x & (x >> 1)); } // 隣接する1のペアの個数

    [[nodiscard]] constexpr i64 next_combination(i64 x) noexcept {
        assert(x != 0);
        i64 t = x | (x - 1); return (t + 1) | (((~t & -~t) - 1) >> (__builtin_ctzll(x) + 1));
    }

    vector<int> popvec(i64 x) noexcept {
        vector<int> ret;
        i64 b = 1;
        for (int k = 0; x >= b; k++, b <<= 1) {
            if (x & b) ret.push_back(k);
        }
        return ret;
    }
}

inline namespace mod_util {
    constexpr int64_t pow_mod_constexpr(int64_t x, int64_t n, int32_t m) noexcept {
        assert(n >= 0);
        if (m == 1) return 0;
        uint32_t _m = (uint32_t)(m);
        uint64_t r = 1; uint64_t y = x % m + (x < 0 ? m : 0);
        while (n) {
            if (n & 1) r = (r * y) % _m;
            y = (y * y) % _m;
            n >>= 1;
        }
        return r;
    }

    constexpr bool is_prime_constexpr(int32_t n) noexcept {
        assert(n >= 0 && n <= 2147483647);
        if (n <= 1) return false;
        if (n == 2 or n == 7 or n == 61) return true;
        if (n % 2 == 0) return false;
        int64_t d = n - 1;
        while (d % 2 == 0) d /= 2;
        constexpr int64_t bases[3] = {2, 7, 61};
        for (int64_t a : bases) {
            int64_t t = d;
            int64_t y = pow_mod_constexpr(a, t, n);
            while (t != n - 1 && y != 1 && y != n - 1) {
                y = y * y % n;
                t <<= 1;
            }
            if (y != n - 1 && t % 2 == 0) {
                return false;
            }
        }
        return true;
    }

    template<uint_fast64_t Modulus>
    class Modint {
    private:
        using u32 = std::uint_fast32_t;
        using u64 = std::uint_fast64_t;
        using i64 = std::int_fast64_t;
        u32 _v = 0;
        static constexpr bool is_prime = (Modulus == 998244353 or Modulus == 1000000007) ? true : is_prime_constexpr(Modulus);
    public:
        static constexpr u32 mod = Modulus;

        constexpr Modint() noexcept = default;
        constexpr Modint(u64 x) noexcept : _v(util::mod(x, mod)) {}
        constexpr Modint(const Modint &r) noexcept = default;
        constexpr Modint &operator =(const Modint &r) noexcept = default;

        static constexpr Modint raw(u64 x) noexcept { Modint ret; ret._v = x; return ret; }
        constexpr u32 val() const noexcept { return _v; }

        constexpr Modint operator +() const noexcept { return *this; }
        constexpr Modint operator -() const noexcept { return raw(_v ? mod - _v : 0); }
        constexpr Modint operator +(const Modint &r) const noexcept { return Modint(*this) += r; }
        constexpr Modint operator +(int q) const noexcept { return Modint(*this) += Modint(q); }
        constexpr Modint operator -(const Modint &r) const noexcept { return Modint(*this) -= r; }
        constexpr Modint operator -(int q) const noexcept { return Modint(*this) -= Modint(q); }
        constexpr Modint operator *(const Modint &r) const noexcept { return Modint(*this) *= r; }
        constexpr Modint operator *(int q) const noexcept { return Modint(*this) *= Modint(q); }
        constexpr Modint operator /(const Modint &r) const noexcept { return Modint(*this) /= r; }
        constexpr Modint operator /(int q) const noexcept { return Modint(*this) /= Modint(q); }

        constexpr Modint &operator ++() noexcept { if (++_v == mod) _v = 0; return *this; }
        constexpr Modint operator ++(signed) noexcept { Modint tmp = *this; ++*this; return tmp; }
        constexpr Modint &operator --() noexcept { if (_v == 0) _v = mod; _v--; return *this; }
        constexpr Modint operator --(signed) noexcept { Modint tmp = *this; --*this; return tmp; }
        constexpr Modint &operator +=(const Modint &r) noexcept { u64 t = _v + r._v; _v = t >= mod ? t - mod : t; return *this; }
        constexpr Modint &operator +=(int q) noexcept { return *this += Modint(q); }
        constexpr Modint &operator -=(const Modint &r) noexcept { u64 t = _v + mod - r._v; _v = t >= mod ? t - mod : t; return *this; }
        constexpr Modint &operator -=(int q) noexcept { return *this -= Modint(q); }
        constexpr Modint &operator *=(const Modint &r) noexcept { _v = (u64)_v * r._v % mod; return *this; }
        constexpr Modint &operator *=(int q) noexcept { return *this *= Modint(q); }
        constexpr Modint &operator /=(const Modint &r) noexcept { return *this *= r.inv(); }
        constexpr Modint &operator /=(int q) noexcept { return *this /= Modint(q); }

        constexpr bool operator ==(const Modint &r) const noexcept { return _v == r._v; }
        constexpr bool operator !=(const Modint &r) const noexcept { return _v != r._v; }
        constexpr bool operator <(const Modint &r) const noexcept { return _v < r._v; }
        constexpr bool operator >(const Modint &r) const noexcept { return _v > r._v; }
        constexpr bool operator <=(const Modint &r) const noexcept { return _v <= r._v; }
        constexpr bool operator >=(const Modint &r) const noexcept { return _v >= r._v; }

        [[nodiscard]] constexpr Modint inv() const noexcept {
            if constexpr (is_prime) {
                return pow(mod - 2);
            } else {
                i64 a = _v, b = mod, u = 1, v = 0;
                while (b) { i64 t = a / b; a -= t * b; swap(a, b); u -= t * v; swap(u, v); }
                return raw(u < 0 ? u + mod : u);
            }
        }
        [[nodiscard]] constexpr Modint pow(i64 n) const noexcept {
            Modint ret = 1, base = *this;
            if (n < 0) { base = base.inv(); n = -n; }
            while (n) {
                if (n & 1) ret *= base;
                base *= base;
                n >>= 1;
            }
            return ret;
        }

        friend istream &operator >>(istream &is, Modint &x) noexcept {
            i64 t; is >> t; x = Modint(t); return is;
        }
        friend ostream &operator <<(ostream &os, const Modint &x) noexcept {
            return os << x._v;
        }
    };
    using mint = Modint<MOD>;

    mint modpow(mint x, int n) noexcept {
        return x.pow(n);
    }
    int modinv(int x, int mod) noexcept;
    int modpow(int x, int n, int mod) noexcept {
        assert(mod > 0);
        if (mod == 1) return 0;
        else if (n == 0) return 1;
        else if (x == 0) return 0;

        if (n < 0) {
            x = modinv(x, mod);
            n = -n;
        }
        int ret = 1;
        x %= mod;
        while (n) {
            if (n & 1) ret = ret * x % mod;
            x = (__int128_t)x * x % mod;
            n /= 2;
        }
        return ret;
    }
    int modinv(int x, int mod) noexcept {
        assert(x > 0 && mod > 0 && gcd(x, mod) == 1);
        if (x == 1) return 1;
        if (mod == 1) return 0;
        if (mod <= 2147483647 && is_prime_constexpr(mod)) {
            return modpow(x, mod - 2, mod);
        } else {
            __int128_t a = x, b = mod, u = 1, v = 0;
            while (b) { __int128_t t = a / b; a -= t * b; swap(a, b); u -= t * v; swap(u, v); }
            return (int)(u < 0 ? u + mod : u);
        }
    }
    // int modinv(__int128_t x, int mod) noexcept {
    //     assert(x >= 0 && mod > 0);
    //     if (x == 1 or x == 0) return 1;
    //     return mod - modinv(mod % x, mod) * (mod / x) % mod;
    // }
}

inline namespace combinatorics {
    vector<mint> _fac, _finv, _inv;
    int _com_size = 0;

    void COMinit(int N) noexcept {
        assert(N > 0);
        _fac.resize(N + 1); _finv.resize(N + 1);  _inv.resize(N + 1);
        _fac[0] = _fac[1] = 1; _finv[0] = _finv[1] = 1; _inv[1] = 1;
        for (int i = 2; i <= N; i++) {
            _fac[i] = _fac[i-1] * mint(i);
            _inv[i] = -_inv[MOD % i] * mint(MOD / i);
            _finv[i] = _finv[i - 1] * _inv[i];
        }
        _com_size = N;
    }

    mint FAC(int N) noexcept {
        assert(N <= _com_size);
        if (N < 0) return 0;
        return _fac[N];
    }
    mint FACinv(int N) noexcept {
        assert(N <= _com_size);
        if (N < 0) return 0;
        return _finv[N];
    }
    mint COM(int N, int K) noexcept {
        assert(N <= _com_size);
        if (N < K) return 0;
        if (N < 0 or K < 0) return 0;
        return _fac[N] * _finv[K] * _finv[N - K];
    }
    mint COMinv(int N, int K) noexcept {
        assert(N <= _com_size);
        if (N < K) return 0;
        if (N < 0 or K < 0) return 0;
        return _finv[N] * _fac[K] * _fac[N - K];
    }
    mint MCOM(const vector<int> &V) noexcept {
        assert(accumulate(V.begin(), V.end(), 0) <= _com_size);
        int N = 0;
        for (int i = 0; i < (int)V.size(); i++) N += V[i];
        mint ret = _fac[N];
        for (int i = 0; i < (int)V.size(); i++) ret *= _finv[V[i]];
        return ret;
    }
    mint PERM(int N, int K) noexcept {
        assert(N <= _com_size);
        if (N < K) return 0;
        if (N < 0 or K < 0) return 0;
        return _fac[N] * _finv[N - K];
    }
    mint NHK(int N, int K) noexcept { // initのサイズに注意
        assert(N <= _com_size);
        // if (N < 0 or K < 0) return 0;
        if (N == 0 && K == 0) return 1;
        return COM(N + K - 1, K);
    }
}

inline namespace structs {
    template<typename T>
    struct Edge {
        int from, to;
        T cost;
        Edge() noexcept {}
        Edge(int to, T cost) noexcept : from(-1), to(to), cost(cost) {}
        Edge(int from, int to, T cost) noexcept : from(from), to(to), cost(cost) {}
        constexpr bool operator ==(const Edge &e) const noexcept {
            return this->from == e.from && this->to == e.to && this->cost == e.cost;
        }
        constexpr bool operator !=(const Edge &e) const noexcept {
            return this->from != e.from or this->to != e.to or this->cost != e.cost;
        }
        constexpr bool operator <(const Edge &e) const noexcept { return this->cost < e.cost; }
        constexpr bool operator >(const Edge &e) const noexcept { return this->cost > e.cost; }
    };

    struct custom_hash {
        static constexpr uint64_t splitmix64(uint64_t x) noexcept {
            x += 0x9e3779b97f4a7c15;
            x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
            x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
            return x ^ (x >> 31);
        }

        size_t operator()(uint64_t x) const noexcept {
            static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
            return splitmix64(x + FIXED_RANDOM);
        }
    };

    class RNG {
        using state_type = uint32_t; // 負数非対応
        using result_type = uint32_t;
    public:
        RNG() noexcept {
            auto now = chrono::high_resolution_clock::now();
            w = static_cast<state_type>(now.time_since_epoch().count() & 0xFFFFFFFF);
        }

        constexpr result_type Int(state_type r) noexcept { // [0, r]
            return _Int(r + 1);
        }
        constexpr result_type Int(state_type l, state_type r) noexcept { // [l, r]
            return _Int(r - l + 1) + l;
        }
        constexpr uint64_t Int64(uint64_t l, uint64_t r) noexcept { // [l, r]
            return _Int64(r - l + 1) + l;
        }

        constexpr double prob() noexcept { // [0, 1]
            return (*this)() * INV_MAX;
        }
        constexpr double Double(double l, double r) noexcept { // [l, r]
            return prob() * (r - l) + l;
        }

        vector<result_type> Seq(int N, state_type l, state_type r) noexcept { // [l, r]
            vector<result_type> ret(N);
            for (int i = 0; i < N; i++) ret[i] = _Int(r - l + 1) + l;
            return ret;
        }
        vector<uint64_t> Seq64(int N, uint64_t l, uint64_t r) noexcept { // [l, r]
            vector<uint64_t> ret(N);
            for (int i = 0; i < N; i++) ret[i] = _Int64(r - l + 1) + l;
            return ret;
        }
        vector<result_type> Perm(int N) noexcept {
            vector<result_type> ret(N);
            iota(ret.begin(), ret.end(), 0);
            for (int i = 0; i < N; i++) {
                int j = _Int(N - i) + i;
                swap(ret[i], ret[j]);
            }
            return ret;
        }
        string Str(int N, bool small = true) noexcept {
            string ret(N, ' ');
            for (int i = 0; i < N; i++) {
                if (small) ret[i] = (char)Int('a', 'z');
                else ret[i] = (char)Int('A', 'Z');
            }
            return ret;
        }

    private:
        state_type x = 123456789, y = 362436039, z = 521288629, w = 88675123;
        constexpr static double INV_MAX = 1.0 / 0xFFFFFFFF;

        constexpr result_type operator()() noexcept {
            state_type t = x ^ (x << 11);
            x = y, y = z, z = w;
            return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));
        }

        constexpr result_type _Int(state_type r) noexcept { // [0, r)
            return ((uint64_t) (*this)() * r) >> 32;
        }
        constexpr uint64_t _Int64(uint64_t r) noexcept { // [0, r)
            uint64_t hi = (*this)();
            uint64_t lo = (*this)();
            __uint128_t full = ((__uint128_t)hi << 32) | lo;
            return (full * (__uint128_t)r) >> 64;
        }
    } rnd;

    template<typename T>
    class Compress {
    public:
        Compress() noexcept = default;

        template<typename... Vecs>
        Compress(const Vecs&... vecs) noexcept {
            (uniqV.insert(uniqV.end(), vecs.begin(), vecs.end()), ...);
            sort(uniqV.begin(), uniqV.end());
            uniqV.erase(unique(uniqV.begin(), uniqV.end()), uniqV.end());
            sz = uniqV.size();
        }

        int size() const noexcept { return sz; }

        [[nodiscard]] vector<int> zip(const vector<T> &V) const noexcept {
            vector<int> ret(V.size());
            for (int i = 0; i < (int)V.size(); i++) {
                ret[i] = encode(V[i]);
            }
            return ret;
        }
        [[nodiscard]] vector<T> unzip(const vector<int> &V) const noexcept {
            vector<T> ret(V.size());
            for (int i = 0; i < (int)V.size(); i++) {
                ret[i] = decode(V[i]);
            }
            return ret;
        }

        [[nodiscard]] int encode(T x) const noexcept { // xが存在しない場合は挿入すべき位置を返す
            auto it = lower_bound(uniqV.begin(), uniqV.end(), x);
            return it - uniqV.begin();
        }
        [[nodiscard]] T decode(int x) const noexcept {
            assert(0 <= x && x < sz);
            return uniqV[x];
        }

    private:
        int sz = 0;
        vector<T> uniqV;
    };
}

inline namespace timer {
    chrono::system_clock::time_point _start;
    void reset() noexcept {
        _start = chrono::system_clock::now();
    }
    ll now() noexcept {
        auto cur = chrono::system_clock::now();
        return chrono::duration_cast<chrono::milliseconds>(cur - _start).count();
    }
}

__attribute__((constructor))
void constructor() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout << fixed << setprecision(10);
    timer::reset();
}

__attribute__((destructor))
void destructor() {
    cerr << "Time: " << timer::now() << "ms" << endl;
}

class UnionFind {
public:
	UnionFind() = default;
    UnionFind(int N) : par(N), sz(N, 1) {
        iota(par.begin(), par.end(), 0);
    }
	int root(int x) {
		if (par[x] == x) return x;
		return (par[x] = root(par[x]));
	}
	bool unite(int x, int y) {
		int rx = root(x);
		int ry = root(y);
        if (rx == ry) return false;
		if (sz[rx] < sz[ry]) swap(rx, ry);
		sz[rx] += sz[ry];
		par[ry] = rx;
        return true;
	}
	bool issame(int x, int y) { return (root(x) == root(y)); }
	int size(int x) { return sz[root(x)]; }
    vector<vector<int>> groups() {
        int N = par.size();
        vector<vector<int>> G(N);
        for (int x = 0; x < N; x++) {
            G[root(x)].push_back(x);
        }
		G.erase( remove_if(G.begin(), G.end(),
            [&](const vector<int>& V) { return V.empty(); }), G.end());
        return G;
    }

private:
	vector<int> par, sz;
};

template<typename T>
class BIT {
public:
    BIT(int N_, int x = 0) : N(N_ + 1) {
        bit[0].assign(N, 0); bit[1].assign(N, 0);
        if (x != 0) {
            for (int i = 0; i < N; i++) add(i, x);
        }
    }
    BIT(const vector<T> &A) : N(A.size() + 1) {
        bit[0].assign(N, 0); bit[1].assign(N, 0);
        for (int i = 0; i < (int)A.size(); i++) add(i, A[i]);
    }
    void add(int l, int r, T x) {
        add_sub(0, l + 1, -x * l); add_sub(0, r + 1, x * r);
        add_sub(1, l + 1, x); add_sub(1, r + 1, -x);
    }
    void add(int i, T x) { add(i, i + 1, x); }
    T sum(int i) const { return sum_sub(0, i) + sum_sub(1, i) * i; }
    T sum(int l, int r) const { return sum(r) - sum(l); }
    T get(int i) const { return sum(i, i + 1); }
    void set(int i, T x) { T s = get(i); add(i, -s + x); }

private:
    int N;
    vector<T> bit[2];
    void add_sub(int p, int i, T x) {
        while (i < N) { bit[p][i] += x; i += (i & -i); }
    }
    T sum_sub(int p, int i) const {
        T ret = T(0);
        while (i > 0) { ret += bit[p][i]; i -= (i & -i); }
        return ret;
    }
};

/* #endregion */

signed main() {
    int A, B;
    cin >> A >> B;
    cout << mod(A, B) << endl;
}
0