結果

問題 No.1685 One by One
ユーザー ecottea
提出日時 2025-07-10 17:40:26
言語 C++17
(gcc 13.3.0 + boost 1.87.0)
結果
WA  
実行時間 -
コード長 25,908 bytes
コンパイル時間 5,836 ms
コンパイル使用メモリ 292,968 KB
実行使用メモリ 7,848 KB
最終ジャッジ日時 2025-07-10 17:40:35
合計ジャッジ時間 7,119 ms
ジャッジサーバーID
(参考情報)
judge4 / judge5
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 2 WA * 2
other AC * 5 WA * 41
権限があれば一括ダウンロードができます

ソースコード

diff #

#ifndef HIDDEN_IN_VS // 折りたたみ用

// 警告の抑制
#define _CRT_SECURE_NO_WARNINGS

// ライブラリの読み込み
#include <bits/stdc++.h>
using namespace std;

// 型名の短縮
using ll = long long; using ull = unsigned long long; // -2^63 ~ 2^63 = 9e18(int は -2^31 ~ 2^31 = 2e9)
using pii = pair<int, int>;	using pll = pair<ll, ll>;	using pil = pair<int, ll>;	using pli = pair<ll, int>;
using vi = vector<int>;		using vvi = vector<vi>;		using vvvi = vector<vvi>;	using vvvvi = vector<vvvi>;
using vl = vector<ll>;		using vvl = vector<vl>;		using vvvl = vector<vvl>;	using vvvvl = vector<vvvl>;
using vb = vector<bool>;	using vvb = vector<vb>;		using vvvb = vector<vvb>;
using vc = vector<char>;	using vvc = vector<vc>;		using vvvc = vector<vvc>;
using vd = vector<double>;	using vvd = vector<vd>;		using vvvd = vector<vvd>;
template <class T> using priority_queue_rev = priority_queue<T, vector<T>, greater<T>>;
using Graph = vvi;

// 定数の定義
const double PI = acos(-1);
int DX[4] = { 1, 0, -1, 0 }; // 4 近傍(下,右,上,左)
int DY[4] = { 0, 1, 0, -1 };
int INF = 1001001001; ll INFL = 4004004003094073385LL; // (int)INFL = INF, (int)(-INFL) = -INF;

// 入出力高速化
struct fast_io { fast_io() { cin.tie(nullptr); ios::sync_with_stdio(false); cout << fixed << setprecision(18); } } fastIOtmp;

// 汎用マクロの定義
#define all(a) (a).begin(), (a).end()
#define sz(x) ((int)(x).size())
#define lbpos(a, x) (int)distance((a).begin(), std::lower_bound(all(a), (x)))
#define ubpos(a, x) (int)distance((a).begin(), std::upper_bound(all(a), (x)))
#define Yes(b) {cout << ((b) ? "Yes\n" : "No\n");}
#define rep(i, n) for(int i = 0, i##_len = int(n); i < i##_len; ++i) // 0 から n-1 まで昇順
#define repi(i, s, t) for(int i = int(s), i##_end = int(t); i <= i##_end; ++i) // s から t まで昇順
#define repir(i, s, t) for(int i = int(s), i##_end = int(t); i >= i##_end; --i) // s から t まで降順
#define repe(v, a) for(const auto& v : (a)) // a の全要素(変更不可能)
#define repea(v, a) for(auto& v : (a)) // a の全要素(変更可能)
#define repb(set, d) for(int set = 0, set##_ub = 1 << int(d); set < set##_ub; ++set) // d ビット全探索(昇順)
#define repis(i, set) for(int i = lsb(set), bset##i = set; i < 32; bset##i -= 1 << i, i = lsb(bset##i)) // set の全要素(昇順)
#define repp(a) sort(all(a)); for(bool a##_perm = true; a##_perm; a##_perm = next_permutation(all(a))) // a の順列全て(昇順)
#define uniq(a) {sort(all(a)); (a).erase(unique(all(a)), (a).end());} // 重複除去
#define EXIT(a) {cout << (a) << endl; exit(0);} // 強制終了
#define inQ(x, y, u, l, d, r) ((u) <= (x) && (l) <= (y) && (x) < (d) && (y) < (r)) // 半開矩形内判定

// 汎用関数の定義
template <class T> inline ll powi(T n, int k) { ll v = 1; rep(i, k) v *= n; return v; }
template <class T> inline bool chmax(T& M, const T& x) { if (M < x) { M = x; return true; } return false; } // 最大値を更新(更新されたら true を返す)
template <class T> inline bool chmin(T& m, const T& x) { if (m > x) { m = x; return true; } return false; } // 最小値を更新(更新されたら true を返す)
template <class T> inline T getb(T set, int i) { return (set >> i) & T(1); }
template <class T> inline T smod(T n, T m) { n %= m; if (n < 0) n += m; return n; } // 非負mod

// 演算子オーバーロード
template <class T, class U> inline istream& operator>>(istream& is, pair<T, U>& p) { is >> p.first >> p.second; return is; }
template <class T> inline istream& operator>>(istream& is, vector<T>& v) { repea(x, v) is >> x; return is; }
template <class T> inline vector<T>& operator--(vector<T>& v) { repea(x, v) --x; return v; }
template <class T> inline vector<T>& operator++(vector<T>& v) { repea(x, v) ++x; return v; }

#endif // 折りたたみ用


#if __has_include(<atcoder/all>)
#include <atcoder/all>
using namespace atcoder;

#ifdef _MSC_VER
#include "localACL.hpp"
#endif

//using mint = modint998244353;
using mint = static_modint<(int)1e9+7>;
//using mint = modint; // mint::set_mod(m);

using vm = vector<mint>; using vvm = vector<vm>; using vvvm = vector<vvm>; using vvvvm = vector<vvvm>; using pim = pair<int, mint>;
#endif


#ifdef _MSC_VER // 手元環境(Visual Studio)
#include "local.hpp"
#else // 提出用(gcc)
int mute_dump = 0;
int frac_print = 0;
#if __has_include(<atcoder/all>)
namespace atcoder {
	inline istream& operator>>(istream& is, mint& x) { ll x_; is >> x_; x = x_; return is; }
	inline ostream& operator<<(ostream& os, const mint& x) { os << x.val(); return os; }
}
#endif
inline int popcount(int n) { return __builtin_popcount(n); }
inline int popcount(ll n) { return __builtin_popcountll(n); }
inline int lsb(int n) { return n != 0 ? __builtin_ctz(n) : 32; }
inline int lsb(ll n) { return n != 0 ? __builtin_ctzll(n) : 64; }
inline int msb(int n) { return n != 0 ? (31 - __builtin_clz(n)) : -1; }
inline int msb(ll n) { return n != 0 ? (63 - __builtin_clzll(n)) : -1; }
#define dump(...)
#define dumpel(v)
#define dump_math(v)
#define input_from_file(f)
#define output_to_file(f)
#define Assert(b) { if (!(b)) { vc MLE(1<<30); EXIT(MLE.back()); } } // RE の代わりに MLE を出す
#endif


void zikken() {
	int N = 20;

	vvi tbl(N);

	repi(n, 1, N) {
		dump(n);

		vvi dp;
		dp.push_back(vi(n));

		repi(m, 1, 30) {
			vvi ndp;

			repea(a, dp) {
				rep(i, n) {
					a[i]++;
					a[(i + 1) % n]--;
					ndp.push_back(a);
					a[i]--;
					a[(i + 1) % n]++;

					a[i]--;
					a[(i + 1) % n]++;
					ndp.push_back(a);
					a[i]++;
					a[(i + 1) % n]--;
				}
			}

			uniq(ndp);
			dp = move(ndp);

			tbl[n - 1].push_back(sz(dp));

			if (tbl[n - 1].back() > (int)5e5) break;
		}
	}

	dumpel(tbl);

	dump_math(tbl);

	exit(0);
}
/*
 0: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
 1: 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
 2: 6 19 37 61 91 127 169 217 271 331 397 469 547 631 721 817 919 1027 1141 1261 1387 1519 1657 1801 1951 2107 2269 2437 2611 2791
 3: 8 27 64 125 216 343 512 729 1000 1331 1728 2197 2744 3375 4096 4913 5832 6859 8000 9261 10648 12167 13824 15625 17576 19683 21952 24389 27000 29791
 4: 10 51 180 501 1131 2221 3951 6531 10201 15231 21921 30601 41631 55401 72331 92871 117501 146731 181101 221181 267571 320901 381831 451051 529281
 5: 12 73 284 835 2036 4347 8408 15069 25420 40821 62932 93743 135604 191255 263856 357017 474828 621889
 6: 14 99 476 1765 5418 14407 33839 71835 140505 257069 445117 736009
 7: 16 129 704 2875 9456 26411 65024 144909 298000 573661
 8: 18 163 996 4645 17718 57799 166344 432073 1027351
 9: 20 201 1360 7001 29112 101941 310472 843471
10: 22 243 1804 10165 46530 180775 614680
11: 24 289 2336 14305 71000 297381 1081088
12: 26 339 2964 19605 104910 474215 1866280
13: 28 393 3696 26265 150780 729905
14: 30 451 4540 34501 211546 1092231
15: 32 513 5504 44545 290592 1594369
16: 34 579 6596 56645 391782 2276743
17: 36 649 7824 71065 519492
18: 38 723 9196 88085 678642
19: 40 801 10720 108001 874728
{{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},{2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31},{6,19,37,61,91,127,169,217,271,331,397,469,547,631,721,817,919,1027,1141,1261,1387,1519,1657,1801,1951,2107,2269,2437,2611,2791},{8,27,64,125,216,343,512,729,1000,1331,1728,2197,2744,3375,4096,4913,5832,6859,8000,9261,10648,12167,13824,15625,17576,19683,21952,24389,27000,29791},{10,51,180,501,1131,2221,3951,6531,10201,15231,21921,30601,41631,55401,72331,92871,117501,146731,181101,221181,267571,320901,381831,451051,529281},{12,73,284,835,2036,4347,8408,15069,25420,40821,62932,93743,135604,191255,263856,357017,474828,621889},{14,99,476,1765,5418,14407,33839,71835,140505,257069,445117,736009},{16,129,704,2875,9456,26411,65024,144909,298000,573661},{18,163,996,4645,17718,57799,166344,432073,1027351},{20,201,1360,7001,29112,101941,310472,843471},{22,243,1804,10165,46530,180775,614680},{24,289,2336,14305,71000,297381,1081088},{26,339,2964,19605,104910,474215,1866280},{28,393,3696,26265,150780,729905},{30,451,4540,34501,211546,1092231},{32,513,5504,44545,290592,1594369},{34,579,6596,56645,391782,2276743},{36,649,7824,71065,519492},{38,723,9196,88085,678642},{40,801,10720,108001,874728}};

これを 2D P-recursive チェッカーにぶち込みコードを自動生成する.
項数が足りないが LLL パワーでゴリ押す → 失敗
*/


//【階乗など(法が大きな素数)】
/*
* Factorial_mint(int N) : O(n)
*	N まで計算可能として初期化する.
*
* mint fact(int n) : O(1)
*	n! を返す.
*
* mint fact_inv(int n) : O(1)
*	1/n! を返す(n が負なら 0 を返す)
*
* mint inv(int n) : O(1)
*	1/n を返す.
*
* mint perm(int n, int r) : O(1)
*	順列の数 nPr を返す.
*
* mint perm_inv(int n, int r) : O(1)
*	順列の数の逆数 1/nPr を返す.
*
* mint bin(int n, int r) : O(1)
*	二項係数 nCr を返す.
*
* mint bin_inv(int n, int r) : O(1)
*	二項係数の逆数 1/nCr を返す.
*
* mint mul(vi rs) : O(|rs|)
*	多項係数 nC[rs] を返す.(n = Σrs)
*
* mint hom(int n, int r) : O(1)
*	重複組合せの数 nHr = n+r-1Cr を返す(0H0 = 1 とする)
*
* mint neg_bin(int n, int r) : O(1)
*	負の二項係数 nCr = (-1)^r -n+r-1Cr を返す(n ≦ 0, r ≧ 0)
*
* mint pochhammer(int x, int n) : O(1)
*	ポッホハマー記号 x^(n) を返す(n ≧ 0)
*
* mint pochhammer_inv(int x, int n) : O(1)
*	ポッホハマー記号の逆数 1/x^(n) を返す(n ≧ 0)
*/
class Factorial_mint {
	int n_max;

	// 階乗と階乗の逆数の値を保持するテーブル
	vm fac, fac_inv;

public:
	// n! までの階乗とその逆数を前計算しておく.O(n)
	Factorial_mint(int n) : n_max(n), fac(n + 1), fac_inv(n + 1) {
		// verify : https://atcoder.jp/contests/dwacon6th-prelims/tasks/dwacon6th_prelims_b

		fac[0] = 1;
		repi(i, 1, n) fac[i] = fac[i - 1] * i;

		fac_inv[n] = fac[n].inv();
		repir(i, n - 1, 0) fac_inv[i] = fac_inv[i + 1] * (i + 1);
	}
	Factorial_mint() : n_max(0) {} // ダミー

	// n! を返す.
	mint fact(int n) const {
		// verify : https://atcoder.jp/contests/dwacon6th-prelims/tasks/dwacon6th_prelims_b

		Assert(0 <= n && n <= n_max);
		return fac[n];
	}

	// 1/n! を返す(n が負なら 0 を返す)
	mint fact_inv(int n) const {
		// verify : https://atcoder.jp/contests/abc289/tasks/abc289_h

		Assert(n <= n_max);
		if (n < 0) return 0;
		return fac_inv[n];
	}

	// 1/n を返す.
	mint inv(int n) const {
		// verify : https://atcoder.jp/contests/exawizards2019/tasks/exawizards2019_d

		Assert(n > 0);
		Assert(n <= n_max);
		return fac[n - 1] * fac_inv[n];
	}

	// 順列の数 nPr を返す.
	mint perm(int n, int r) const {
		// verify : https://atcoder.jp/contests/abc172/tasks/abc172_e

		Assert(n <= n_max);

		if (r < 0 || n - r < 0) return 0;
		return fac[n] * fac_inv[n - r];
	}

	// 順列の数 nPr の逆数を返す.
	mint perm_inv(int n, int r) const {
		// verify : https://yukicoder.me/problems/no/3139

		Assert(n <= n_max);
		Assert(0 <= r); Assert(r <= n);

		return fac_inv[n] * fac[n - r];
	}

	// 二項係数 nCr を返す.
	mint bin(int n, int r) const {
		// verify : https://judge.yosupo.jp/problem/binomial_coefficient_prime_mod

		Assert(n <= n_max);
		if (r < 0 || n - r < 0) return 0;
		return fac[n] * fac_inv[r] * fac_inv[n - r];
	}

	// 二項係数の逆数 1/nCr を返す.
	mint bin_inv(int n, int r) const {
		// verify : https://www.codechef.com/problems/RANDCOLORING

		Assert(n <= n_max);
		Assert(r >= 0);
		Assert(n - r >= 0);
		return fac_inv[n] * fac[r] * fac[n - r];
	}

	// 多項係数 nC[rs] を返す.
	mint mul(const vi& rs) const {
		// verify : https://yukicoder.me/problems/no/2141

		if (*min_element(all(rs)) < 0) return 0;
		int n = accumulate(all(rs), 0);
		Assert(n <= n_max);

		mint res = fac[n];
		repe(r, rs) res *= fac_inv[r];

		return res;
	}

	// 重複組合せの数 nHr = n+r-1Cr を返す(0H0 = 1 とする)
	mint hom(int n, int r) {
		// verify : https://mojacoder.app/users/riantkb/problems/toj_ex_2

		if (n == 0) return (int)(r == 0);
		if (r < 0 || n - 1 < 0) return 0;
		Assert(n + r - 1 <= n_max);
		return fac[n + r - 1] * fac_inv[r] * fac_inv[n - 1];
	}

	// 負の二項係数 nCr を返す(n ≦ 0, r ≧ 0)
	mint neg_bin(int n, int r) {
		// verify : https://atcoder.jp/contests/abc345/tasks/abc345_g

		if (n == 0) return (int)(r == 0);
		if (r < 0 || -n - 1 < 0) return 0;
		Assert(-n + r - 1 <= n_max);
		return (r & 1 ? -1 : 1) * fac[-n + r - 1] * fac_inv[r] * fac_inv[-n - 1];
	}

	// ポッホハマー記号 x^(n) を返す(n ≧ 0)
	mint pochhammer(int x, int n) {
		// verify : https://atcoder.jp/contests/agc070/tasks/agc070_c

		int x2 = x + n - 1;
		if (x <= 0 && 0 <= x2) return 0;

		if (x > 0) {
			Assert(x2 <= n_max);
			return fac[x2] * fac_inv[x - 1];
		}
		else {
			Assert(-x <= n_max);
			return (n & 1 ? -1 : 1) * fac[-x] * fac_inv[-x2 - 1];
		}
	}

	// ポッホハマー記号の逆数 1/x^(n) を返す(n ≧ 0)
	mint pochhammer_inv(int x, int n) {
		// verify : https://atcoder.jp/contests/agc070/tasks/agc070_c

		int x2 = x + n - 1;
		Assert(!(x <= 0 && 0 <= x2));

		if (x > 0) {
			Assert(x2 <= n_max);
			return fac_inv[x2] * fac[x - 1];
		}
		else {
			Assert(-x <= n_max);
			return (n & 1 ? -1 : 1) * fac_inv[-x] * fac[-x2 - 1];
		}
	}
};


// しょうがないので場合分けによる激遅コードを書く.
// 初項を大量に集めるのが目的なので,多項式オーダーでさえあれば何でもいい.
mint TLE(int n, int M) {
	Factorial_mint fm(n + M + 10);

	mint res = 0;

	if (n % 2 == 0) {
		repi(m, 0, M) {
			mint pres = res;

			repi(t, 0, M - m) repi(s, 0, M - m - t) repi(i, 0, n / 2 - 1) repi(j, 0, n / 2 - 1) {
				if ((s ^ t ^ m ^ M) & 1) continue;
				if (t > 0 && i == 0) continue;
				if (s > 0 && j == 0) continue;

				int wgt = (m == 0 ? 1 : 2);

				mint add = fm.bin(n - 1, i) * fm.bin(n - 1 - i, j);
				if (i > 0) add *= fm.bin(t - 1, i - 1);
				if (j > 0) add *= fm.bin(s - 1, j - 1);
				//dump("m,t,s,i,j:", m, t, s, i, j, ":", add);
				add *= wgt;

				res += add;
			}

			//dump(m, ":", res - pres);
		}
	}
	else {
		// m : median
		repi(m, 0, M) {
			mint pres = res;

			if (m == 0) {
				// パリティ一致
				repi(t, 0, M - m) repi(s, 0, M - m - t) {
					if ((s ^ t ^ m ^ M) & 1) continue;

					repi(i, 0, n / 2) repi(j, 0, n / 2) {
						if (t > 0 && i == 0) continue;
						if (s > 0 && j == 0) continue;

						int wgt = 1;

						mint add = fm.bin(n - 1, i) * fm.bin(n - 1 - i, j);
						if (i > 0) add *= fm.bin(t - 1, i - 1);
						if (j > 0) add *= fm.bin(s - 1, j - 1);
						if (add == 0) continue;

						add *= wgt;
						dump("0,m,t,s,i,j:", m, t, s, i, j, ":", add);

						res += add;
					}
				}

				// パリティ不一致
				// x : neg cnt, y : pos cnt
				repi(x, 0, n / 2) repi(y, 0, n / 2) {
					// All 1 から
					if (x <= y) {
						int M_rem = M - 1 - 2 * x - (n - 1 - x - y);

						// s : ad neg sum, t : ad pos sum 
						repi(s, 0, M_rem) repi(t, 0, M_rem - s) {
							if ((1 ^ (2 * x) ^ (n - 1 - x - y) ^ s ^ t ^ M) & 1) continue;
							int wgt = 1;

							mint add = fm.bin(n - 1, x) * fm.bin(n - 1 - x, y);
							if (x > 0 || s > 0) add *= fm.bin(x + s - 1, s);
							if (y > 0 || t > 0) add *= fm.bin(y + t - 1, t);
							add *= wgt;
							if (add == 0) continue;

							dump("1,m,x,y,s,t:", m, x, y, s, t, ":", add);

							res += add;
						}
					}
					// All -1 から
					else {
						int M_rem = M - 1 - 2 * y - (n - 1 - x - y);

						// s : ad neg sum, t : ad pos sum 
						repi(s, 0, M_rem) repi(t, 0, M_rem - s) {
							if ((1 ^ (2 * y) ^ (n - 1 - x - y) ^ s ^ t ^ M) & 1) continue;
							int wgt = 1;

							mint add = fm.bin(n - 1, x) * fm.bin(n - 1 - x, y);
							if (x > 0 || s > 0) add *= fm.bin(x + s - 1, s);
							if (y > 0 || t > 0) add *= fm.bin(y + t - 1, t);
							add *= wgt;
							if (add == 0) continue;

							dump("1,m,x,y,s,t:", m, x, y, s, t, ":", add);

							res += add;
						}
					}
				}
			}
			else {
				// パリティ一致
				repi(t, 0, M - m) repi(s, 0, M - m - t) repi(i, 0, n / 2 - 1) repi(j, 0, n / 2) {
					if ((s ^ t ^ m ^ M) & 1) continue;
					if (t > 0 && i == 0) continue;
					if (s > 0 && j == 0) continue;

					int wgt = 2;

					mint add = fm.bin(n - 1, i) * fm.bin(n - 1 - i, j);
					if (i > 0) add *= fm.bin(t - 1, i - 1);
					if (j > 0) add *= fm.bin(s - 1, j - 1);
					add *= wgt;
					dump("0,m,t,s,i,j:", m, t, s, i, j, ":", add);

					res += add;
				}

				// パリティ不一致
				// x : neg cnt, y : pos cnt
				repi(x, 0, n / 2 - 1) repi(y, 0, n / 2) {
					// All m+1 から
					if ((m - 1) + 2 * y + (n - 1 - x - y) >= (m + 1) + 2 * x + (n - 1 - x - y)) {
						int M_rem = M - (m + 1) - 2 * x - (n - 1 - x - y);

						// s : ad neg sum, t : ad pos sum 
						repi(s, 0, M_rem) repi(t, 0, M_rem - s) {
							if (((m + 1) ^ (2 * x) ^ (n - 1 - x - y) ^ s ^ t ^ M) & 1) continue;
							int wgt = 2;

							mint add = fm.bin(n - 1, x) * fm.bin(n - 1 - x, y);
							if (x > 0 || s > 0) add *= fm.bin(x + s - 1, s);
							if (y > 0 || t > 0) add *= fm.bin(y + t - 1, t);
							add *= wgt;
							if (add == 0) continue;

							dump("1,m,x,y,s,t:", m, x, y, s, t, ":", add);

							res += add;
						}
					}
					// All m-1 から
					else {
						int M_rem = M - (m - 1) - 2 * y - (n - 1 - x - y);

						// s : ad neg sum, t : ad pos sum 
						repi(s, 0, M_rem) repi(t, 0, M_rem - s) {
							if (((m + 1) ^ (2 * y) ^ (n - 1 - x - y) ^ s ^ t ^ M) & 1) continue;
							int wgt = 2;

							mint add = fm.bin(n - 1, x) * fm.bin(n - 1 - x, y);
							if (x > 0 || s > 0) add *= fm.bin(x + s - 1, s);
							if (y > 0 || t > 0) add *= fm.bin(y + t - 1, t);
							add *= wgt;
							if (add == 0) continue;

							dump("1,m,x,y,s,t:", m, x, y, s, t, ":", add);

							res += add;
						}
					}
				}
			}

			dump(m, ":", res - pres);
		}
	}

	return res;
}


void zikken2() {
	int N = 35;

	vvm tbl(N, vm(N));

	repi(n, 1, N) {
		dump(n);
		repi(m, 1, N) {
			mute_dump = 1;
			tbl[n - 1][m - 1] = TLE(n, m);
			mute_dump = 0;
		}
	}
	
	dumpel(tbl);
	dump_math(tbl);

	exit(0);
}
/*
(略)

これを 2D P-recursive チェッカーにぶち込みコードを自動生成する.
*/


int main() {
//	input_from_file("input.txt");
//	output_to_file("output.txt");

//	zikken2();

	int n, m;
	cin >> n >> m;

	vm dp(m + 1 + 10);

	auto D = [&](const mint& x, const mint& y) { return dp[y.val()]; };
	auto P = [&](const mint& x, int n) { mint res = 1; rep(hoge, n) res *= x; return res; };

	{
		vm dp2{ -1, 1, 2, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, \
38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70 };
		dp2.resize(n + 1);
		auto D1 = [&](const mint& x) { return dp2[x.val()]; };
		repi(i, 10, n) {
			mint nn = i;
			dp2[i] = -((nn * (241996577 + 252667810 * nn) * D1(-1 + nn)) / (241996577 + nn * (10671233 + 747332197 * nn)));
		}
		dp[1] = dp2[n];
	}

	{
		vm dp2{ -1, 1, 3, 19, 27, 51, 73, 99, 129, 163, 201, 243, 289, 339, 393, 451, \
513, 579, 649, 723, 801, 883, 969, 1059, 1153, 1251, 1353, 1459, \
1569, 1683, 1801, 1923, 2049, 2179, 2313, 2451 };
		dp2.resize(n + 1);
		auto D1 = [&](const mint& x) { return dp2[x.val()]; };
		repi(i, 10, n) {
			mint nn = i;
			dp2[i] = ((6241921445 - 2 * nn * (4178823388 + nn * (-1975412017 + 350290987 * nn))) * D1(-2 + nn) +
				5 * (75036767 + nn * (-287984418 + (369645089 - 175009936 * nn) * nn)) * D1(-1 + nn)) /
				(302844111 + nn * (25306763 + 5 * nn * (70295333 + 84873672 * nn)))
				;
		}
		dp[2] = dp2[n];
	}

	{
		vm dp2{ -1,1, 4, 37, 64, 180, 284, 476, 704, 996, 1360, 1804, 2336, 2964, 3696, \
4540, 5504, 6596, 7824, 9196, 10720, 12404, 14256, 16284, 18496, \
20900, 23504, 26316, 29344, 32596, 36080, 39804, 43776, 48004, 52496, \
57260 };
		dp2.resize(n + 1);
		auto D1 = [&](const mint& x) { return dp2[x.val()]; };
		repi(i, 10, n) {
			mint nn = i;
			dp2[i] = ((10572523803 + nn * (-14072110253 + (5559864651 - 717795020 * nn) * nn)) * D1(-3 + nn) +
				(-944723011 + 2 * nn * (252299180 + 27 * (2242319 - 1730379 * nn) * nn)) * D1(-2 + nn) -
				(518869005 + 2 * nn * (70942705 + 22 * nn * (-474633 + 2185736 * nn))) * D1(-1 + nn)) /
				(266416062 + nn * (672390244 + nn * (11148766 + 92592137 * nn)));
		}
		dp[3] = dp2[n];
	}

	{
		vm dp2{ -1,1, 5, 61, 125, 501, 835, 1765, 2875, 4645, 7001, 10165, 14305, \
19605, 26265, 34501, 44545, 56645, 71065, 88085, 108001, 131125, \
157785, 188325, 223105, 262501, 306905, 356725, 412385, 474325, \
543001, 618885, 702465, 794245, 894745, 1004501 };
		dp2.resize(n + 1);
		auto D1 = [&](const mint& x) { return dp2[x.val()]; };
		repi(i, 10, n) {
			mint nn = i;
			dp2[i] = ((56078927807 + nn * (-42469256279 + (10710098461 - 900290529 * nn) * nn)) * D1(-4 + nn) +
				(12674231301 + nn * (-15836163660 + 7 * (883412886 - 113633911 * nn) * nn)) * D1(-3 + nn) +
				(5078220962 + nn * (-7777409982 + (4013704021 - 732186705 * nn) * nn)) * D1(-2 + nn) +
				(284705508 + nn * (-1097581829 + (419866223 - 176848856 * nn) * nn)) * D1(-1 + nn)) /
				(447371989 + 3 * nn * (149051219 + 2 * nn * (140390767 + 65872759 * nn)));
		}
		dp[4] = dp2[n];
	}

	{
		vm dp2{ -1,1, 6, 91, 216, 1131, 2036, 5418, 9456, 17718, 29112, 46530, 71000, \
104910, 150780, 211546, 290592, 391782, 519492, 678642, 874728, \
1113854, 1402764, 1748874, 2160304, 2645910, 3215316, 3878946, \
4648056, 5534766, 6552092, 7713978, 9035328, 10532038, 12221028, \
14120274 };
		dp2.resize(n + 1);
		auto D1 = [&](const mint& x) { return dp2[x.val()]; };
		repi(i, 10, n) {
			mint nn = i;
			dp2[i] = ((35309978286 - 2 * nn * (14211248465 + nn * (-3823984464 + 350290987 * nn))) * D1(-4 + nn) +
				(20249816626 - 22 * nn * (1010155081 + nn * (-367316907 + 44751722 * nn))) * D1(-3 + nn) -
				(2919121016 + nn * (-2154886837 + nn * (507759257 + 17940144 * nn))) * D1(-2 + nn) -
				(122472762 + nn * (1295596213 + nn * (-1200927681 + 448328188 * nn))) * D1(-1 + nn)) /
				(223000650 + nn * (209968884 + nn * (622859097 + 848611831 * nn)));
		}
		dp[5] = dp2[n];
	}

	{
		vm dp2{ -1,1, 7, 127, 343, 2221, 4347, 14407, 26411, 57799, 101941, 180775, \
297381, 474215, 729905, 1092231, 1594369, 2276743, 3188017, 4386151, \
5939521, 7928103, 10444721, 13596359, 17505537, 22311751, 28172977, \
35267239, 43794241, 53977063, 66063921, 80329991, 97079297, \
116646663, 139399729, 165741031 };
		dp2.resize(n + 1);
		auto D1 = [&](const mint& x) { return dp2[x.val()]; };
		repi(i, 10, n) {
			mint nn = i;
			dp2[i] = ((16502370821 + nn * (-10293327245 + nn * (950309559 + 416268756 * nn - 70878986 * P(nn, 2)))) * D1(-4 + nn) +
				(-11411285714 + nn * (12036659566 + nn * (-5112721194 + (1082798579 - 101831537 * nn) * nn))) * D1(-3 + nn) +
				(-13176691569 + nn * (24091766198 + nn * (-18067864821 + (6246361499 - 843416160 * nn) * nn))) * D1(-2 + nn) +
				(-1114833924 + nn * (3609184784 + nn * (-4838295358 + (3310044237 - 985718821 * nn) * nn))) * D1(-1 + nn)) /
				(6096411 + nn * (245074792 + nn * (485035896 + nn * (624843037 + 998154517 * nn))));
		}
		dp[6] = dp2[n];
	}

	{
		vm dp2{ -1,1, 8, 169, 512, 3951, 8408, 33839, 65024, 166344, 310472, 614680, \
1081088, 1866280, 3066968, 4892536, 7579136, 11450248, 16915008, \
24489176, 34814848, 48682472, 67055296, 91096376, 122198272, \
162015560, 212500288, 275940504, 355001984, 452773288, 572814272, \
719208184, 896617472, 110343425, 366389817, 671530577 };
		dp2.resize(n + 1);
		auto D1 = [&](const mint& x) { return dp2[x.val()]; };
		repi(i, 10, n) {
			mint nn = i;
			dp2[i] = ((-547664913480 + nn * (442369875428 + nn * (-133645175028 + (17912422693 - 900290529 * nn) * nn))) * D1(-5 + nn) +
				(-82296489515 + nn * (77220915100 + nn * (-27561693317 + (4460987639 - 280627680 * nn) * nn))) * D1(-4 + nn) +
				3725289806 * D1(-3 + nn) - 3461901965 * D1(-2 + nn) + 321589940 * D1(-1 + nn) +
				nn * ((1937345240 + nn * (-4350832017 + 13 * (137149198 - 17631703 * nn) * nn)) * D1(-3 + nn) +
					(5835849431 + nn * (-4179027030 + (1282355363 - 167325254 * nn) * nn)) * D1(-2 + nn) -
					(1938520694 + nn * (-1113806974 + nn * (326675156 + 40426199 * nn))) * D1(-1 + nn))) /
				(843339770 + nn * (352707777 + nn * (257868593 + nn * (918765039 + 382118213 * nn))));
		}
		dp[7] = dp2[n];
	}

	{
		vm dp2{ -1, 1, 9, 217, 729, 6531, 15069, 71835, 144909, 432073, 843471, 1871145, \
3486591, 6539625, 11422251, 19439241, 31898043, 50940297, 79305553, \
120709737, 180013761, 263511081, 379248849, 537400521, 750695169, \
34908994, 409424842, 897865634, 528808115, 336583380, 362170933, \
654193382, 270019024, 276979914, 753713156, 791633543 };
		dp2.resize(n + 1);
		auto D1 = [&](const mint& x) { return dp2[x.val()]; };
		repi(i, 10, n) {
			mint nn = i;
			dp2[i] = ((-70393986509 + nn * (69175765335 + nn * (-25567030015 + 4164868952 * nn - 252667810 * P(nn, 2)))) * D1(-5 + nn) +
				(-199276323253 + nn * (210745627715 + nn * (-83879121369 + (14826869260 - 982237139 * nn) * nn))) * D1(-4 + nn) -
				3 * (22544170522 * D1(-3 + nn) + 4865944523 * D1(-2 + nn) - 39893643 * D1(-1 + nn)) +
				nn * ((90602506847 + nn * (-45074299411 + (9951085918 - 830958735 * nn) * nn)) * D1(-3 + nn) +
					(26928386507 - 2 * nn * (9760613179 + nn * (-3194300615 + 410411703 * nn))) * D1(-2 + nn) -
					(386435855 + nn * (796495721 - 792034540 * nn + 318462138 * P(nn, 2))) * D1(-1 + nn))) /
				(327548 + nn * (375225605 + nn * (566841503 + nn * (285641197 + 794850800 * nn))));
		}
		dp[7] = dp2[n];
	}

	dump(dp);

	repi(j, 9, m) {
        dump("j:", j);

		mint nn1 = n;
		mint nn2 = j;

		dp[j] = 1; // CE が出るほどやばすぎるので削除
	}

    EXIT(dp[m]); // ここまでにかかる時間と,あと 0 除算してないかだけ見る.
}
0