This documentation is automatically generated by online-judge-tools/verification-helper
#define PROBLEM "https://judge.yosupo.jp/problem/aplusb"
#include "../../../src/template/template.hpp"
#include "../../../src/random/random_number_generator.hpp"
#include "../../../src/template/dynamic_modint.hpp"
#include "../../../src/math/lucas.hpp"
#include "../../../src/math/miller_rabin.hpp"
using mint = modint;
void test() {
static Lucas<mint> binom;
int n = rng(1, 200000), k = rng(0, n);
mint ans = 1;
int cnt = 0;
rep(i, 1, k + 1) {
int p = n - (i - 1), q = i;
while(p % mint::mod() == 0) {
cnt++;
p /= mint::mod();
}
while(q % mint::mod() == 0) {
cnt--;
q /= mint::mod();
}
ans *= mint(p) / q;
}
if(cnt > 0) ans = 0;
assert(binom(n, k).val() == ans.val());
}
int main(void) {
int p = 1;
while(!miller_rabin(p)) {
p = rng(2, 200000);
}
mint::set_mod(p);
constexpr int test_num = 1000;
rep(_, 0, test_num) {
test();
}
int a, b;
cin >> a >> b;
cout << a + b << '\n';
}
#line 1 "verify/unit_test/math/lucas.test.cpp"
#define PROBLEM "https://judge.yosupo.jp/problem/aplusb"
#line 2 "src/template/template.hpp"
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using P = pair<long long, long long>;
#define rep(i, a, b) for(long long i = (a); i < (b); ++i)
#define rrep(i, a, b) for(long long i = (a); i >= (b); --i)
constexpr long long inf = 4e18;
struct SetupIO {
SetupIO() {
ios::sync_with_stdio(0);
cin.tie(0);
cout << fixed << setprecision(30);
}
} setup_io;
#line 3 "src/random/random_number_generator.hpp"
struct RandomNumberGenerator {
RandomNumberGenerator()
: mt(chrono::steady_clock::now().time_since_epoch().count()) {}
template <typename T>
inline T operator()(const T lower, const T upper) {
static_assert(is_integral_v<T> or is_floating_point_v<T>);
assert(lower <= upper);
if constexpr(is_integral_v<T>) {
uniform_int_distribution<T> dist(lower, upper);
return dist(mt);
} else if constexpr(is_floating_point_v<T>) {
uniform_real_distribution<T> dist(lower, upper);
return dist(mt);
}
}
template <typename T>
inline vector<T> vec(const int n, const T lower, const T upper, const bool dup = true) {
static_assert(is_integral_v<T> or is_floating_point_v<T>);
assert(0 <= n and n <= (int)1e8);
assert(lower <= upper);
if(n == 0) return {};
vector<T> res(n);
if(dup or is_floating_point_v<T>) {
for(int i = 0; i < n; ++i) res[i] = this->operator()(lower, upper);
} else {
assert(upper - lower + 1 >= n);
if(upper - lower + 1 >= 2 * n) {
set<T> used;
while((int)used.size() < n) {
const T a = this->operator()(lower, upper);
used.insert(a);
}
int i = 0;
for(const T a : used) {
res[i] = a;
++i;
}
} else {
const vector<int> p = perm(upper - lower + 1, false);
for(int i = 0; i < n; ++i) {
res[i] = p[i] + lower;
}
}
}
return res;
}
inline vector<int> perm(const int n, const bool one = true) {
assert(0 <= n and n <= (int)1e8);
vector<int> res(n);
for(int i = 0; i < n; ++i) res[i] = i + one;
for(int i = n - 1; i > 0; --i) {
swap(res[i], res[this->operator()(0, i)]);
}
return res;
}
inline pair<vector<int>, vector<int>> tree(const int n, const bool one = true) {
assert(0 <= n and n <= (int)1e8);
if(n <= 1) return {{}, {}};
if(n == 2) return {{0 + one}, {1 + one}};
vector<int> u(n - 1), v(n - 1);
const vector<int> pruefer = vec(n - 2, 0, n - 1);
set<int> st;
vector<int> cnt(n);
for(int i = 0; i < n; ++i) st.insert(i);
auto add = [&](const int x) -> void {
if(x > n) return;
if(cnt[x] == 0) st.erase(x);
++cnt[x];
};
auto del = [&](const int x) -> void {
if(x > n) return;
--cnt[x];
if(cnt[x] == 0) st.insert(x);
};
for(int i = 0; i < n - 2; ++i) add(pruefer[i]);
for(int i = 0; i < n - 2; ++i) {
const int a = *st.begin();
const int b = pruefer[i];
u[i] = a + one;
v[i] = b + one;
del(b);
add(a);
}
const int a = *st.begin();
add(a);
const int b = *st.begin();
u[n - 2] = a + one;
v[n - 2] = b + one;
return {u, v};
}
template <typename T>
inline tuple<vector<int>, vector<int>, vector<T>> weighted_tree(const int n, const T lower, const T upper, const bool one = true) {
static_assert(is_integral_v<T> or is_floating_point_v<T>);
assert(0 <= n and n <= (int)1e8);
assert(lower <= upper);
if(n == 0) return {{}, {}, {}};
const auto [u, v] = tree(n, one);
const vector<T> w = vec(n - 1, lower, upper, true);
return {u, v, w};
}
inline pair<vector<int>, vector<int>> graph(const int n, const int m, const bool one = true) {
assert(0 <= n and n <= (int)1e8);
assert(0 <= m and m <= (int)min((ll)1e8, 1ll * n * (n - 1) / 2));
vector<int> u, v;
u.reserve(m);
v.reserve(m);
if(1ll * n * (n - 1) / 2 >= 2e6) {
set<pair<int, int>> edge;
while((int)edge.size() < m) {
const int a = this->operator()(0, n - 1);
const int b = this->operator()(0, n - 1);
if(a >= b) continue;
edge.insert({a, b});
}
for(const auto& [a, b] : edge) {
u.push_back(a + one);
v.push_back(b + one);
}
} else {
vector<pair<int, int>> edge;
edge.reserve(n * (n - 1) / 2);
for(int i = 0; i < n; ++i) {
for(int j = i + 1; j < n; ++j) {
edge.push_back({i, j});
}
}
const vector<int> p = perm(n * (n - 1) / 2, false);
for(int i = 0; i < m; ++i) {
u.push_back(edge[p[i]].first + one);
v.push_back(edge[p[i]].second + one);
}
}
return {u, v};
}
template <typename T>
inline tuple<vector<int>, vector<int>, vector<T>> weighted_graph(const int n, const int m, const T lower, const T upper, const bool one = true) {
static_assert(is_integral_v<T> or is_floating_point_v<T>);
assert(0 <= n and n <= (int)1e8);
assert(0 <= m and m <= (int)min((ll)1e8, 1ll * n * (n - 1) / 2));
assert(lower <= upper);
const auto [u, v] = graph(n, m, one);
const vector<T> w = vec(m, lower, upper, true);
return {u, v, w};
}
inline pair<vector<int>, vector<int>> connected_graph(const int n, const int m, const bool one = true) {
assert(0 <= n and n <= (int)1e8);
assert(max(n - 1, 0) <= m and m <= (int)min((ll)1e8, 1ll * n * (n - 1) / 2));
if(n <= 1) return {{}, {}};
vector<int> u, v;
u.reserve(m);
v.reserve(m);
auto [ut, vt] = tree(n, false);
if(1ll * n * (n - 1) / 2 >= 2e6) {
set<pair<int, int>> edge;
for(int i = 0; i < n - 1; ++i) {
edge.insert({min(ut[i], vt[i]), max(ut[i], vt[i])});
}
while((int)edge.size() < m) {
const int a = this->operator()(0, n - 1);
const int b = this->operator()(0, n - 1);
if(a >= b) continue;
edge.insert({a, b});
}
for(const auto& [a, b] : edge) {
u.push_back(a + one);
v.push_back(b + one);
}
} else {
set<pair<int, int>> used;
for(int i = 0; i < n - 1; ++i) {
u.push_back(ut[i] + one);
v.push_back(vt[i] + one);
used.insert({min(ut[i], vt[i]), max(ut[i], vt[i])});
}
vector<pair<int, int>> edge;
edge.reserve(n * (n - 1) / 2 - (n - 1));
for(int i = 0; i < n; ++i) {
for(int j = i + 1; j < n; ++j) {
if(used.find({i, j}) == used.end()) edge.push_back({i, j});
}
}
const vector<int> p = perm(n * (n - 1) / 2 - (n - 1), false);
for(int i = 0; i < m - (n - 1); ++i) {
u.push_back(edge[p[i]].first + one);
v.push_back(edge[p[i]].second + one);
}
}
return {u, v};
}
template <typename T>
inline tuple<vector<int>, vector<int>, vector<T>> weighted_connected_graph(const int n, const int m, const T lower, const T upper, const bool one = true) {
static_assert(is_integral_v<T> or is_floating_point_v<T>);
assert(0 <= n and n <= (int)1e8);
assert(max(n - 1, 0) <= m and m <= (int)min((ll)1e8, 1ll * n * (n - 1) / 2));
assert(lower <= upper);
const auto [u, v] = connected_graph(n, m, one);
const vector<T> w = vec(m, lower, upper, true);
return {u, v, w};
}
inline string parenthesis(const int n) {
assert(0 <= n and n <= 1e8);
string res = "";
int N = n, M = n;
for(int i = 0; i < 2 * n; ++i) {
if(this->operator()(0.0l, 1.0l) > 1.0l * (N - M) * (N + 1) / ((N - M + 1) * (N + M))) {
res += "(";
--M;
} else {
res += ")";
--N;
}
}
return res;
}
private:
mt19937_64 mt;
} rng;
#line 3 "src/template/dynamic_modint.hpp"
struct Barrett {
explicit Barrett(const unsigned int m)
: _m(m), im((unsigned long long)(-1) / m + 1) {}
inline unsigned int umod() const {
return _m;
}
inline unsigned int mul(const unsigned int a, const unsigned int b) const {
unsigned long long z = a;
z *= b;
const unsigned long long x = (unsigned long long)(((unsigned __int128)(z)*im) >> 64);
unsigned int v = (unsigned int)(z - x * _m);
if(_m <= v) v += _m;
return v;
}
private:
unsigned int _m;
unsigned long long im;
};
template <int id>
struct DynamicModint {
using mint = DynamicModint;
static int mod() {
return (int)bt.umod();
}
static void set_mod(const int m) {
assert(1 <= m);
bt = Barrett(m);
}
static mint raw(const int v) {
mint a;
a._v = v;
return a;
}
DynamicModint()
: _v(0) {}
template <class T>
DynamicModint(const T& v) {
static_assert(is_integral_v<T>);
if(is_signed_v<T>) {
long long x = (long long)(v % (long long)(umod()));
if(x < 0) x += umod();
_v = (unsigned int)(x);
} else _v = (unsigned int)(v % umod());
}
unsigned int val() const {
return _v;
}
mint& operator++() {
++_v;
if(_v == umod()) _v = 0;
return *this;
}
mint& operator--() {
if(_v == 0) _v = umod();
--_v;
return *this;
}
mint operator++(int) {
mint res = *this;
++*this;
return res;
}
mint operator--(int) {
mint res = *this;
--*this;
return res;
}
mint& operator+=(const mint& rhs) {
_v += rhs._v;
if(_v >= umod()) _v -= umod();
return *this;
}
mint& operator-=(const mint& rhs) {
_v += mod() - rhs._v;
if(_v >= umod()) _v -= umod();
return *this;
}
mint& operator*=(const mint& rhs) {
_v = bt.mul(_v, rhs._v);
return *this;
}
mint& operator/=(const mint& rhs) {
return *this *= rhs.inv();
}
mint operator+() const {
return *this;
}
mint operator-() const {
return mint() - *this;
}
mint pow(long long n) const {
assert(0 <= n);
if(n == 0) return 1;
mint x = *this, r = 1;
while(1) {
if(n & 1) r *= x;
n >>= 1;
if(n == 0) return r;
x *= x;
}
}
mint inv() const {
const auto eg = inv_gcd(_v, mod());
assert(eg.first == 1);
return eg.second;
}
friend mint operator+(const mint& lhs, const mint& rhs) {
return mint(lhs) += rhs;
}
friend mint operator-(const mint& lhs, const mint& rhs) {
return mint(lhs) -= rhs;
}
friend mint operator*(const mint& lhs, const mint& rhs) {
return mint(lhs) *= rhs;
}
friend mint operator/(const mint& lhs, const mint& rhs) {
return mint(lhs) /= rhs;
}
friend bool operator==(const mint& lhs, const mint& rhs) {
return lhs._v == rhs._v;
}
friend bool operator!=(const mint& lhs, const mint& rhs) {
return lhs._v != rhs._v;
}
friend istream& operator>>(istream& in, mint& x) {
long long a;
in >> a;
x = a;
return in;
}
friend ostream& operator<<(ostream& out, const mint& x) {
return out << x.val();
}
private:
unsigned int _v = 0;
static Barrett bt;
inline static unsigned int umod() {
return bt.umod();
}
inline static pair<long long, long long> inv_gcd(const long long a, const long long b) {
if(a == 0) return {b, 0};
long long s = b, t = a, m0 = 0, m1 = 1;
while(t) {
const long long u = s / t;
s -= t * u;
m0 -= m1 * u;
swap(s, t);
swap(m0, m1);
}
if(m0 < 0) m0 += b / s;
return {s, m0};
}
};
template <int id>
Barrett DynamicModint<id>::bt(998244353);
using modint = DynamicModint<-1>;
#line 3 "src/math/lucas.hpp"
template <typename mint>
struct Lucas {
Lucas()
: mod(mint::mod()), fact(mint::mod()), ifact(mint::mod()) {
fact[0] = 1;
for(int i = 1; i < mod; ++i) fact[i] = fact[i - 1] * i;
ifact[mod - 1] = fact[mod - 1].inv();
for(int i = mod - 1; i >= 1; --i) ifact[i - 1] = ifact[i] * i;
}
mint operator()(long long n, long long k) const {
if(n < 0 or n < k or k < 0) return 0;
mint res = 1;
while(n > 0) {
const long long n0 = n % mod, k0 = k % mod;
if(n0 < k0) return 0;
res *= fact[n0] * ifact[k0] * ifact[n0 - k0];
n /= mod;
k /= mod;
}
return res;
}
private:
int mod;
vector<mint> fact, ifact;
};
#line 3 "src/math/miller_rabin.hpp"
constexpr __int128_t pow_mod_128(__int128_t x, __int128_t n, const __int128_t mod) {
assert(n >= 0 and mod >= 1);
x %= mod;
if(x < 0) x += mod;
__int128_t res = 1;
while(n > 0) {
if(n & 1) res = res * x % mod;
x = x * x % mod;
n >>= 1;
}
return res;
}
constexpr bool miller_rabin(const long long n) {
if(n <= 2) return n == 2;
if(n % 2 == 0) return false;
constexpr long long bases[7] = {2, 325, 9375, 28178, 450775, 9780504, 1795265022};
long long d = n - 1;
while(d % 2 == 0) d /= 2;
for(const long long base : bases) {
if(base % n == 0) continue;
long long t = d;
long long y = pow_mod_128(base, t, n);
while(t != n - 1 and y != 1 and y != n - 1) {
y = (__int128_t)y * y % n;
t *= 2;
}
if(y != n - 1 and t % 2 == 0) return false;
}
return true;
}
#line 7 "verify/unit_test/math/lucas.test.cpp"
using mint = modint;
void test() {
static Lucas<mint> binom;
int n = rng(1, 200000), k = rng(0, n);
mint ans = 1;
int cnt = 0;
rep(i, 1, k + 1) {
int p = n - (i - 1), q = i;
while(p % mint::mod() == 0) {
cnt++;
p /= mint::mod();
}
while(q % mint::mod() == 0) {
cnt--;
q /= mint::mod();
}
ans *= mint(p) / q;
}
if(cnt > 0) ans = 0;
assert(binom(n, k).val() == ans.val());
}
int main(void) {
int p = 1;
while(!miller_rabin(p)) {
p = rng(2, 200000);
}
mint::set_mod(p);
constexpr int test_num = 1000;
rep(_, 0, test_num) {
test();
}
int a, b;
cin >> a >> b;
cout << a + b << '\n';
}