結果
| 問題 | No.83 最大マッチング |
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2026-01-05 00:03:06 |
| 言語 | C++23 (gcc 15.2.0 + boost 1.90.0) |
| 結果 |
AC
|
| 実行時間 | 1 ms / 5,000 ms |
| + 513µs | |
| コード長 | 24,985 bytes |
| 記録 | |
| コンパイル時間 | 4,165 ms |
| コンパイル使用メモリ | 541,928 KB |
| 実行使用メモリ | 5,888 KB |
| 最終ジャッジ日時 | 2026-07-20 01:11:23 |
| 合計ジャッジ時間 | 5,180 ms |
|
ジャッジサーバーID (参考情報) |
judge3_0 / judge2_0 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 10 |
ソースコード
#include <cstdio>
#include <vector>
#include <iostream>
#include <deque>
#include <queue>
#include <tuple>
#include <map>
#include <set>
#include <algorithm>
#include <string>
/**
* ACLibrary-segtree
* Ref : https://atcoder.github.io/ac-library/master/document_ja/
*/
#include <cassert>
#include <functional>
/**
* ACLibrary-internalbit
* Ref : https://atcoder.github.io/ac-library/master/document_ja/
*/
#ifdef _MSC_VER
#include <intrin.h>
#endif
#if __cplusplus >= 202002L
#include <bit>
#endif
namespace atcoder {
namespace internal {
#if __cplusplus >= 202002L
using std::bit_ceil;
#else
// @return same with std::bit::bit_ceil
unsigned int bit_ceil(unsigned int n) {
unsigned int x = 1;
while (x < (unsigned int)(n)) x *= 2;
return x;
}
#endif
// @param n `1 <= n`
// @return same with std::bit::countr_zero
int countr_zero(unsigned int n) {
#ifdef _MSC_VER
unsigned long index;
_BitScanForward(&index, n);
return index;
#else
return __builtin_ctz(n);
#endif
}
// @param n `1 <= n`
// @return same with std::bit::countr_zero
constexpr int countr_zero_constexpr(unsigned int n) {
int x = 0;
while (!(n & (1 << x))) x++;
return x;
}
} // namespace internal
} // namespace atcoder
namespace atcoder {
#if __cplusplus >= 201703L
template <class S, auto op, auto e> struct segtree {
static_assert(std::is_convertible_v<decltype(op), std::function<S(S, S)>>,
"op must work as S(S, S)");
static_assert(std::is_convertible_v<decltype(e), std::function<S()>>,
"e must work as S()");
#else
template <class S, S (*op)(S, S), S (*e)()> struct segtree {
#endif
public:
segtree() : segtree(0) {}
explicit segtree(int n) : segtree(std::vector<S>(n, e())) {}
explicit segtree(const std::vector<S>& v) : _n(int(v.size())) {
size = (int)internal::bit_ceil((unsigned int)(_n));
log = internal::countr_zero((unsigned int)size);
d = std::vector<S>(2 * size, e());
for (int i = 0; i < _n; i++) d[size + i] = v[i];
for (int i = size - 1; i >= 1; i--) {
update(i);
}
}
void set(int p, S x) {
assert(0 <= p && p < _n);
p += size;
d[p] = x;
for (int i = 1; i <= log; i++) update(p >> i);
}
S get(int p) const {
assert(0 <= p && p < _n);
return d[p + size];
}
S prod(int l, int r) const {
assert(0 <= l && l <= r && r <= _n);
S sml = e(), smr = e();
l += size;
r += size;
while (l < r) {
if (l & 1) sml = op(sml, d[l++]);
if (r & 1) smr = op(d[--r], smr);
l >>= 1;
r >>= 1;
}
return op(sml, smr);
}
S all_prod() const { return d[1]; }
template <bool (*f)(S)> int max_right(int l) const {
return max_right(l, [](S x) { return f(x); });
}
template <class F> int max_right(int l, F f) const {
assert(0 <= l && l <= _n);
assert(f(e()));
if (l == _n) return _n;
l += size;
S sm = e();
do {
while (l % 2 == 0) l >>= 1;
if (!f(op(sm, d[l]))) {
while (l < size) {
l = (2 * l);
if (f(op(sm, d[l]))) {
sm = op(sm, d[l]);
l++;
}
}
return l - size;
}
sm = op(sm, d[l]);
l++;
} while ((l & -l) != l);
return _n;
}
template <bool (*f)(S)> int min_left(int r) const {
return min_left(r, [](S x) { return f(x); });
}
template <class F> int min_left(int r, F f) const {
assert(0 <= r && r <= _n);
assert(f(e()));
if (r == 0) return 0;
r += size;
S sm = e();
do {
r--;
while (r > 1 && (r % 2)) r >>= 1;
if (!f(op(d[r], sm))) {
while (r < size) {
r = (2 * r + 1);
if (f(op(d[r], sm))) {
sm = op(d[r], sm);
r--;
}
}
return r + 1 - size;
}
sm = op(d[r], sm);
} while ((r & -r) != r);
return 0;
}
private:
int _n, size, log;
std::vector<S> d;
void update(int k) { d[k] = op(d[2 * k], d[2 * k + 1]); }
};
} // namespace atcoder
#include <boost/rational.hpp>
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/multiprecision/cpp_dec_float.hpp>
using namespace std;
using namespace atcoder;
using namespace boost;
namespace mp = boost::multiprecision;
//Integer-Related
typedef long long i64;
typedef unsigned long long ui64;
typedef mp::int128_t i128;
typedef mp::uint128_t ui128;
//Float-Related
typedef mp::cpp_dec_float_100 float100;
typedef mp::cpp_dec_float_50 float50;
//vector-Related
template<typename T>
using vv = vector<vector<T>>;
template<typename T>
using vvv = vector<vector<vector<T>>>;
typedef vector<i64> vi64;
typedef vector<bool> vbool;
typedef vv<i64> vvi64;
typedef vv<bool> vvbool;
typedef vvv<i64> vvvi64;
typedef vvv<bool> vvvbool;
typedef pair<i64, i64> pi64;
typedef vector<string> vstr;
//これで最大値優先
template<typename Val_T, typename Pred = less<Val_T>>
using prque = priority_queue<Val_T, vector<Val_T>, Pred>;
//set-Related
#include <unordered_set>
typedef set<i64> si64;
typedef multiset<i64> msi64;
typedef unordered_set<i64> usi64;
//Calculation-Related
inline i64 rm(const i64 l, const i64 r) {
i64 val = l % r;
if (val >= 0) {
return val;
}
else {
return val + r;
}
}
template<typename T>
T r_accumulate(const vector<T>& vec) {
return std::accumulate(vec.begin(), vec.end(), T{});
}
template <typename T>
void r_insert(vector<T>& to, vector<T>& from) {
ranges::copy(from, back_inserter(to));
}
constexpr std::string repeater3030(const std::string& s, int number) {
std::string cur = "";
for (i64 i = 0; i < number; i++)
{
cur += s;
}
return cur;
}
constexpr std::string repeater3030(const char& c, int number) {
string s(1, c);
return repeater3030(s, number);
}
constexpr i64 pow_i64(i64 base, i64 exp) {
i64 res = 1LL;
while (exp > 0LL)
{
if (exp & 1) {
res *= base;
}
exp >>= 1LL;
base *= base;
}
return res;
}
template<typename T>
T eqmin(T& a, T b) {
a = min(a, b);
return a;
}
template<typename T>
T eqmax(T& a, T b) {
a = max(a, b);
return a;
}
//Output-Related
template <typename T, typename U>
std::ostream& operator<<(std::ostream& os, const std::pair<T, U>& p) {
os << "(" << p.first << ", " << p.second << ")";
return os;
}
template<typename T>
inline void output(const T elem) {
std::cout << elem << std::endl;
}
#ifndef __INTELLISENSE__
template<typename T1, typename T2>
inline void output(const pair<T1, T2> elem) {
std::cout << "(" << elem.first << "," << elem.second << ")" << std::endl;
}
template<typename T>
inline void output(const vector<T>& vec) {
for (T elem : vec) {
std::cout << elem << " ";
}
std::cout << std::endl;
}
template<typename T>
inline void output(const vector<vector<T>>& vvec) {
for (vector<T> vec : vvec) {
std::cout << "(";
for (T elem : vec) {
std::cout << elem << " ";
}
std::cout << ")";
}
std::cout << std::endl;
}
template<typename T>
inline void output(const vector<vector<vector<T>>>& vvvec) {
for (vector<vector<T>> vvec : vvvec)
{
std::cout << "[";
for (vector<T> vec : vvec) {
std::cout << "(";
for (T elem : vec) {
std::cout << elem << " ";
}
std::cout << ")";
}
std::cout << "]" << std::endl;
}
}
#endif
template<typename T>
inline void output_iter(const T& iter) {
for (auto&& elem : iter)
{
std::cout << elem << " ";
}
std::cout << std::endl;
}
/*
* Mod I64 (Fork)
* Ref : https://noshi91.hatenablog.com/entry/2019/03/31/174006
* Submit : https://atcoder.jp/contests/abc414/tasks/abc414_e
* Note : Modulusはsqrt(long long の最大値)以下である必要がある
*/
#include <cstdint>
/**
* ACLibrary-math
* Ref : https://atcoder.github.io/ac-library/master/document_ja/
*/
/**
* ACLibrary-internalmath
* Ref : https://atcoder.github.io/ac-library/master/document_ja/
*/
#include <utility>
#ifdef _MSC_VER
#include <intrin.h>
#endif
namespace atcoder {
namespace internal {
// @param m `1 <= m`
// @return x mod m
constexpr long long safe_mod(long long x, long long m) {
x %= m;
if (x < 0) x += m;
return x;
}
// Fast modular multiplication by barrett reduction
// Reference: https://en.wikipedia.org/wiki/Barrett_reduction
// NOTE: reconsider after Ice Lake
struct barrett {
unsigned int _m;
unsigned long long im;
// @param m `1 <= m`
explicit barrett(unsigned int m) : _m(m), im((unsigned long long)(-1) / m + 1) {}
// @return m
unsigned int umod() const { return _m; }
// @param a `0 <= a < m`
// @param b `0 <= b < m`
// @return `a * b % m`
unsigned int mul(unsigned int a, unsigned int b) const {
// [1] m = 1
// a = b = im = 0, so okay
// [2] m >= 2
// im = ceil(2^64 / m)
// -> im * m = 2^64 + r (0 <= r < m)
// let z = a*b = c*m + d (0 <= c, d < m)
// a*b * im = (c*m + d) * im = c*(im*m) + d*im = c*2^64 + c*r + d*im
// c*r + d*im < m * m + m * im < m * m + 2^64 + m <= 2^64 + m * (m + 1) < 2^64 * 2
// ((ab * im) >> 64) == c or c + 1
unsigned long long z = a;
z *= b;
#ifdef _MSC_VER
unsigned long long x;
_umul128(z, im, &x);
#else
unsigned long long x =
(unsigned long long)(((unsigned __int128)(z)*im) >> 64);
#endif
unsigned long long y = x * _m;
return (unsigned int)(z - y + (z < y ? _m : 0));
}
};
// @param n `0 <= n`
// @param m `1 <= m`
// @return `(x ** n) % m`
constexpr long long pow_mod_constexpr(long long x, long long n, int m) {
if (m == 1) return 0;
unsigned int _m = (unsigned int)(m);
unsigned long long r = 1;
unsigned long long y = safe_mod(x, m);
while (n) {
if (n & 1) r = (r * y) % _m;
y = (y * y) % _m;
n >>= 1;
}
return r;
}
// Reference:
// M. Forisek and J. Jancina,
// Fast Primality Testing for Integers That Fit into a Machine Word
// @param n `0 <= n`
constexpr bool is_prime_constexpr(int n) {
if (n <= 1) return false;
if (n == 2 || n == 7 || n == 61) return true;
if (n % 2 == 0) return false;
long long d = n - 1;
while (d % 2 == 0) d /= 2;
constexpr long long bases[3] = {2, 7, 61};
for (long long a : bases) {
long long t = d;
long long 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 <int n> constexpr bool is_prime = is_prime_constexpr(n);
// @param b `1 <= b`
// @return pair(g, x) s.t. g = gcd(a, b), xa = g (mod b), 0 <= x < b/g
constexpr std::pair<long long, long long> inv_gcd(long long a, long long b) {
a = safe_mod(a, b);
if (a == 0) return {b, 0};
// Contracts:
// [1] s - m0 * a = 0 (mod b)
// [2] t - m1 * a = 0 (mod b)
// [3] s * |m1| + t * |m0| <= b
long long s = b, t = a;
long long m0 = 0, m1 = 1;
while (t) {
long long u = s / t;
s -= t * u;
m0 -= m1 * u; // |m1 * u| <= |m1| * s <= b
// [3]:
// (s - t * u) * |m1| + t * |m0 - m1 * u|
// <= s * |m1| - t * u * |m1| + t * (|m0| + |m1| * u)
// = s * |m1| + t * |m0| <= b
auto tmp = s;
s = t;
t = tmp;
tmp = m0;
m0 = m1;
m1 = tmp;
}
// by [3]: |m0| <= b/g
// by g != b: |m0| < b/g
if (m0 < 0) m0 += b / s;
return {s, m0};
}
// Compile time primitive root
// @param m must be prime
// @return primitive root (and minimum in now)
constexpr int primitive_root_constexpr(int m) {
if (m == 2) return 1;
if (m == 167772161) return 3;
if (m == 469762049) return 3;
if (m == 754974721) return 11;
if (m == 998244353) return 3;
int divs[20] = {};
divs[0] = 2;
int cnt = 1;
int x = (m - 1) / 2;
while (x % 2 == 0) x /= 2;
for (int i = 3; (long long)(i)*i <= x; i += 2) {
if (x % i == 0) {
divs[cnt++] = i;
while (x % i == 0) {
x /= i;
}
}
}
if (x > 1) {
divs[cnt++] = x;
}
for (int g = 2;; g++) {
bool ok = true;
for (int i = 0; i < cnt; i++) {
if (pow_mod_constexpr(g, (m - 1) / divs[i], m) == 1) {
ok = false;
break;
}
}
if (ok) return g;
}
}
template <int m> constexpr int primitive_root = primitive_root_constexpr(m);
// @param n `n < 2^32`
// @param m `1 <= m < 2^32`
// @return sum_{i=0}^{n-1} floor((ai + b) / m) (mod 2^64)
unsigned long long floor_sum_unsigned(unsigned long long n,
unsigned long long m,
unsigned long long a,
unsigned long long b) {
unsigned long long ans = 0;
while (true) {
if (a >= m) {
ans += n * (n - 1) / 2 * (a / m);
a %= m;
}
if (b >= m) {
ans += n * (b / m);
b %= m;
}
unsigned long long y_max = a * n + b;
if (y_max < m) break;
// y_max < m * (n + 1)
// floor(y_max / m) <= n
n = (unsigned long long)(y_max / m);
b = (unsigned long long)(y_max % m);
std::swap(m, a);
}
return ans;
}
} // namespace internal
} // namespace atcoder
namespace atcoder {
long long pow_mod(long long x, long long n, int m) {
assert(0 <= n && 1 <= m);
if (m == 1) return 0;
internal::barrett bt((unsigned int)(m));
unsigned int r = 1, y = (unsigned int)(internal::safe_mod(x, m));
while (n) {
if (n & 1) r = bt.mul(r, y);
y = bt.mul(y, y);
n >>= 1;
}
return r;
}
long long inv_mod(long long x, long long m) {
assert(1 <= m);
auto z = internal::inv_gcd(x, m);
assert(z.first == 1);
return z.second;
}
// (rem, mod)
std::pair<long long, long long> crt(const std::vector<long long>& r,
const std::vector<long long>& m) {
assert(r.size() == m.size());
int n = int(r.size());
// Contracts: 0 <= r0 < m0
long long r0 = 0, m0 = 1;
for (int i = 0; i < n; i++) {
assert(1 <= m[i]);
long long r1 = internal::safe_mod(r[i], m[i]), m1 = m[i];
if (m0 < m1) {
std::swap(r0, r1);
std::swap(m0, m1);
}
if (m0 % m1 == 0) {
if (r0 % m1 != r1) return {0, 0};
continue;
}
// assume: m0 > m1, lcm(m0, m1) >= 2 * max(m0, m1)
// (r0, m0), (r1, m1) -> (r2, m2 = lcm(m0, m1));
// r2 % m0 = r0
// r2 % m1 = r1
// -> (r0 + x*m0) % m1 = r1
// -> x*u0*g = r1-r0 (mod u1*g) (u0*g = m0, u1*g = m1)
// -> x = (r1 - r0) / g * inv(u0) (mod u1)
// im = inv(u0) (mod u1) (0 <= im < u1)
long long g, im;
std::tie(g, im) = internal::inv_gcd(m0, m1);
long long u1 = (m1 / g);
// |r1 - r0| < (m0 + m1) <= lcm(m0, m1)
if ((r1 - r0) % g) return {0, 0};
// u1 * u1 <= m1 * m1 / g / g <= m0 * m1 / g = lcm(m0, m1)
long long x = (r1 - r0) / g % u1 * im % u1;
// |r0| + |m0 * x|
// < m0 + m0 * (u1 - 1)
// = m0 + m0 * m1 / g - m0
// = lcm(m0, m1)
r0 += x * m0;
m0 *= u1; // -> lcm(m0, m1)
if (r0 < 0) r0 += m0;
}
return {r0, m0};
}
long long floor_sum(long long n, long long m, long long a, long long b) {
assert(0 <= n && n < (1LL << 32));
assert(1 <= m && m < (1LL << 32));
unsigned long long ans = 0;
if (a < 0) {
unsigned long long a2 = internal::safe_mod(a, m);
ans -= 1ULL * n * (n - 1) / 2 * ((a2 - a) / m);
a = a2;
}
if (b < 0) {
unsigned long long b2 = internal::safe_mod(b, m);
ans -= 1ULL * n * ((b2 - b) / m);
b = b2;
}
return ans + internal::floor_sum_unsigned(n, m, a, b);
}
} // namespace atcoder
template <i64 Modulus>
class modI64 {
private:
i64 val;
public:
constexpr modI64(const i64 x = 0) noexcept : val(x% Modulus) {
assert(x >= 0);
}
modI64 inv() const {
return modI64(inv_mod(val, Modulus));
}
modI64 pow(i64 exp) const {
modI64 res = 1LL;
modI64 base = val;
while (exp > 0LL)
{
if (exp & 1) {
res *= base;
}
exp >>= 1LL;
base *= base;
}
return res;
}
i64 value() const {
return val;
}
constexpr modI64 operator+(const modI64 rhs) const noexcept {
return modI64(*this) += rhs;
}
constexpr modI64 operator-(const modI64 rhs) const noexcept {
return modI64(*this) -= rhs;
}
constexpr modI64 operator*(const modI64 rhs) const noexcept {
return modI64(*this) *= rhs;
}
constexpr modI64 operator/(const modI64 rhs) const noexcept {
return modI64(*this) /= rhs;
}
constexpr modI64& operator+=(const modI64 rhs) noexcept {
val += rhs.val;
if (val >= Modulus) {
val -= Modulus;
}
return *this;
}
constexpr modI64& operator-=(const modI64 rhs) noexcept {
if (val < rhs.val) {
val += Modulus;
}
val -= rhs.val;
return *this;
}
constexpr modI64& operator*=(const modI64 rhs) noexcept {
val = val * rhs.val % Modulus;
return *this;
}
constexpr modI64& operator/=(modI64 rhs) noexcept {
i64 div = inv_mod(rhs.val, Modulus);
val = val * div % Modulus;
return *this;
}
constexpr bool operator==(const modI64& rhs) const noexcept {
return val == rhs.val;
}
constexpr bool operator!=(const modI64& rhs) const noexcept {
return val != rhs.val;
}
friend ostream& operator<<(ostream& os, const modI64& x) {
return os << x.val;
}
};
typedef modI64<998244353> mi64;
//typedef modI64<1000000007> mi64;
typedef vv<mi64> vvmi64;
typedef vector<mi64> vmi64;
/*
* Point-Related(IntegerOnly)
* Author : WhiteKnight
* Submit:https://atcoder.jp/contests/abc421/tasks/abc421_d
*/
template <typename T1 = long long, typename T2 = double>
struct Point {
private:
void single_rect_rotate(Point<T1> min_anchor, i64 size) {
Point<T1> res = { y - min_anchor.y + min_anchor.x, size - 1 - (x - min_anchor.x) + min_anchor.y };
x = res.x;
y = res.y;
}
public:
T1 x, y;
Point() : x(0), y(0) {}
Point(T1 x_val, T1 y_val) : x(x_val), y(y_val) {}
Point& operator+=(const Point& rhs) {
x += rhs.x;
y += rhs.y;
return *this;
}
Point& operator-=(const Point& rhs) {
x -= rhs.x;
y -= rhs.y;
return *this;
}
Point& operator*=(T1 scalar) {
x *= scalar;
y *= scalar;
return *this;
}
Point& operator/=(T1 scalar) {
x /= scalar;
y /= scalar;
return *this;
}
/**
* @brief ベクトルの大きさを計算します。
* @return ベクトルの大きさ。
*/
T2 magnitude() const {
return std::sqrt(static_cast<T2>(x) * x + static_cast<T2>(y) * y);
}
/**
* @brief ベクトルを五種類に大別して向きを表す。
* @return T1型の正規化されたベクトル。
*/
Point<T1> direction() const {
return Point<T1>(sign(x),sign(y));
}
/**
* @brief このベクトルを正規化した新しいベクトルを返します。
* @return T2型の正規化されたベクトル。
*/
Point<T2> normalized() const {
T2 mag = magnitude();
if (mag > 0) {
return Point<T2>(x / mag, y / mag);
}
return Point<T2>(0.0, 0.0);
}
//included
bool in(i64 min_x,i64 max_x,i64 min_y,i64 max_y) {
return min_x <= x && x <= max_x && min_y <= y && y <= max_y;
}
//min_anchor : incl, clockwise
void rect_rotate(Point<T1> min_anchor, i64 size, i64 cnt) {
for (i64 i = 0; i < cnt % 4; i++)
{
single_rect_rotate(min_anchor, size);
}
}
};
template <typename T1, typename T2>
inline Point<T1,T2> operator+(Point<T1, T2> lhs, const Point<T1, T2>& rhs) {
return lhs += rhs;
}
template <typename T1, typename T2>
inline Point<T1, T2> operator-(Point<T1, T2> lhs, const Point<T1, T2>& rhs) {
return lhs -= rhs;
}
template <typename T1, typename T2>
inline Point<T1, T2> operator*(Point<T1, T2> lhs, T1 scalar) {
return lhs *= scalar;
}
template <typename T1, typename T2>
inline Point<T1, T2> operator*(T1 scalar, Point<T1, T2> rhs) {
return rhs *= scalar;
}
template <typename T1, typename T2>
inline Point<T1, T2> operator/(Point<T1, T2> lhs, T1 scalar) {
return lhs /= scalar;
}
template <typename T1, typename T2>
inline bool operator==(const Point<T1, T2>& lhs, const Point<T1, T2>& rhs) {
return lhs.x == rhs.x && lhs.y == rhs.y;
}
template <typename T1, typename T2>
inline bool operator!=(const Point<T1, T2>& lhs, const Point<T1, T2>& rhs) {
return !(lhs == rhs);
}
/**
* @brief 2点間のユークリッド距離(直線距離)を計算します。
* @param p1 始点
* @param p2 終点
* @return double型の距離
*/
template <typename T1, typename T2>
inline T2 distance_euclidean(const Point<T1,T2>& p1, const Point<T1,T2>& p2) {
T2 dx = static_cast<T2>(p1.x) - p2.x;
T2 dy = static_cast<T2>(p1.y) - p2.y;
return std::sqrt(dx * dx + dy * dy);
}
/**
* @brief 2点間のマンハッタン距離を計算します。
* @param p1 始点
* @param p2 終点
* @return 座標と同じ型の距離
*/
template <typename T1, typename T2>
inline T1 distance_manhattan(const Point<T1, T2>& p1, const Point<T1, T2>& p2) {
return std::abs(p1.x - p2.x) + std::abs(p1.y - p2.y);
}
template <typename T1, typename T2>
std::ostream& operator<<(std::ostream& os, const Point<T1, T2>& p) {
os << "(" << p.x << ", " << p.y << ")";
return os;
}
using point = Point<long long,double>;
using q64 = rational<i64>;
/*
* Submit : https://atcoder.jp/contests/abc297/tasks/abc297_c
*/
void replace(string& S, string from, string to) {
assert(from.size() == to.size());
size_t start_pos = 0;
while ((start_pos = S.find(from, start_pos)) != std::string::npos) {
S.replace(start_pos, from.length(), to);
start_pos += to.length();
}
}
vi64 get_digits(i64 val) {
assert(val >= 0);
if (val == 0) {
return { 0 };
}
vi64 res;
while (val > 0)
{
res.push_back(val % 10);
val /= 10;
}
return res;
}
//0-indexedで処理していたものから0部分をはねる
template<typename T>
vv<T> cut_false(vv<T>& base) {
vv<T> res = base;
res.erase(res.begin());
for (auto&& e : res)
{
e.erase(e.begin());
}
return res;
}
std::array<point, 4> gridOn = {
point(1,0),point(0,1),point(-1,0),point(0,-1)
};
/**
* Graph一式
* Author : WhiteKnight
*/
struct Dest {
i64 to;
i64 cost;
};
typedef vector<vector<Dest>> wgraphList;//Weighted,List
typedef vector<vector<i64>> sgraphList;//Simple,List
typedef vector<Dest> vedge;
typedef vvi64 wgraphMat;//Weighted,Matrix
wgraphList translate_simple_weight(sgraphList graph) {
i64 N = graph.size();
wgraphList res(N);
for (i64 i = 0; i < N; i++)
{
for (auto&& e : graph[i])
{
res[i].push_back({e,1});
}
}
return res;
}
template<i64 INF>
wgraphList translate_mat_list(wgraphMat graph){
i64 N = graph.size();
wgraphList res(N);
for (i64 i = 0; i < N; i++)
{
for (i64 j = 0; j < N; j++)
{
if(graph[i][j] >= INF){
continue;
}
res[i].push_back({ j,graph[i][j] });
}
}
return res;
}
//Main Flow
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout << setprecision(15);
i64 N;
cin >> N;
string ans = repeater3030('1',N/2);
N %= 2;
if(N){
ans[0] = '7';
}
output(ans);
return 0;
}