結果

問題 No.1414 東大文系数学2021第2問改
ユーザー iaNTUiaNTU
提出日時 2021-02-27 05:51:38
言語 C++17
(gcc 12.3.0 + boost 1.83.0)
結果
MLE  
実行時間 -
コード長 15,178 bytes
コンパイル時間 1,963 ms
コンパイル使用メモリ 201,432 KB
実行使用メモリ 690,656 KB
最終ジャッジ日時 2024-04-10 15:10:11
合計ジャッジ時間 9,231 ms
ジャッジサーバーID
(参考情報)
judge3 / judge2
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 MLE -
testcase_01 MLE -
testcase_02 TLE -
testcase_03 MLE -
testcase_04 MLE -
testcase_05 MLE -
testcase_06 -- -
testcase_07 -- -
testcase_08 -- -
testcase_09 -- -
testcase_10 -- -
testcase_11 -- -
testcase_12 -- -
testcase_13 -- -
testcase_14 -- -
testcase_15 -- -
testcase_16 -- -
testcase_17 -- -
testcase_18 -- -
testcase_19 -- -
testcase_20 -- -
testcase_21 -- -
testcase_22 -- -
testcase_23 -- -
testcase_24 -- -
testcase_25 -- -
testcase_26 -- -
権限があれば一括ダウンロードができます

ソースコード

diff #

// Exported by Exporter.exe

// Included from C.cpp
// Compile flags -Wall -Wextra -Wshadow -D_GLIBCXX_ASSERTIONS -DDEBUG -ggdb3 -fmax-errors=2
#include <bits/stdc++.h>
using namespace std;
#define PB push_back
#define F first
#define S second
#define MP make_pair
#define MTP make_tuple
#define R Read
#define RD Read_Digit
#define RP Read_P
#define RL Read_Loop
#define RLD Read_Loop_Digit
#define RLP Read_Loop_P
typedef long long int ll;
typedef unsigned long long int ull;

constexpr int kN = 1 << 25;
constexpr int kMod = 998244353;
// constexpr int kMod = int(1E9 + 7);
// constexpr int kInf = 0x3f3f3f3f;
// constexpr ll kInf = 0x3f3f3f3f3f3f3f3f;
// constexpr double kPi = acos(-1);
// constexpr double kEps = 1E-9;


// Included from C:\Users\ianli\Desktop\CP\template\Various\Fast_IO\Fast_IO.cpp
// --- Get ---
static inline char Get_Raw_Char() {
	static char buf[1 << 16], *p = buf, *end = buf;
	if (p == end) {
		if ((end = buf + fread(buf, 1, 1 << 16, stdin)) == buf) return '\0';
		p = buf;
	}
	return *p++;
}

static inline int Get_Digit() {
	char c = Get_Raw_Char();
	while (!isdigit(c)) c = Get_Raw_Char();
	return int(c - '0');
}

template <typename T> static inline int Get_P() {
	static_assert(is_integral<T>::value);
	char c = Get_Raw_Char();
	while (!isdigit(c)) c = Get_Raw_Char();
	T ret = int(c - '0');
	while (isdigit(c = Get_Raw_Char())) ret = ret * 10 + int(c - '0');
	return ret;
}

template <typename T> static inline int Get() {
	static_assert(is_integral<T>::value);
	char c = Get_Raw_Char();
	bool neg = false;
	while (!isdigit(c)) {
		if (c == '-') neg = true;
		c = Get_Raw_Char();
	}
	T ret = int(c - '0');
	while (isdigit(c = Get_Raw_Char())) ret = ret * 10 + int(c - '0');
	if (neg) return -ret;
	return ret;
}

// --- Read ---
template <typename T> static inline void Read_P(T &n) {
	static_assert(is_integral<T>::value);
	char c = Get_Raw_Char();
	while (!isdigit(c)) c = Get_Raw_Char();
	n = int(c - '0');
	while (isdigit(c = Get_Raw_Char())) n = n * 10 + int(c - '0');
	return ;
}

template <typename T> static inline void Read(T &n) {
	static_assert(is_integral<T>::value);
	char c = Get_Raw_Char();
	bool neg = false;
	while (!isdigit(c)) {
		if (c == '-') neg = true;
		c = Get_Raw_Char();
	}
	n = int(c - '0');
	while (isdigit(c = Get_Raw_Char())) n = n * 10 + int(c - '0');
	if (neg) n = -n;
	return ;
}

template <typename T> static inline void Read_Digit(T &n) {
	static_assert(is_integral<T>::value);
	char c = Get_Raw_Char();
	while (!isdigit(c)) c = Get_Raw_Char();
	n = int(c - '0');
	return ;
}

// --- Read multiple ---
template <typename T, typename... Targs> static inline void Read(T &n, Targs&... Fargs) {
	Read(n);
	return Read(Fargs...);
}

template <typename T, typename... Targs> static inline void Read_Digit(T &n, Targs&... Fargs) {
	Read_Digit(n);
	return Read_Digit(Fargs...);
}

template <typename T, typename... Targs> static inline void Read_P(T &n, Targs&... Fargs) {
	Read_P(n);
	return Read_P(Fargs...);
}

// --- Read Loop ---
template <typename T> static inline void Read_Loop_i(int i, T *a) {return Read(a[i]);}
template <typename T, typename... Targs> static inline void Read_Loop_i(int i, T *a, Targs*... Fargs) {
	Read(a[i]);
	return Read_Loop_i(i, Fargs...);
}
template <typename... Targs> static inline void Read_Loop(int n, Targs*... Fargs) {
	for (int i = 1; i <= n; i++) Read_Loop_i(i, Fargs...);
	return ;
}

template <typename T> static inline void Read_Loop_Digit_i(int i, T *a) {return Read_Digit(a[i]);}
template <typename T, typename... Targs> static inline void Read_Loop_Digit_i(int i, T *a, Targs*... Fargs) {
	Read_Digit(a[i]);
	return Read_Loop_Digit_i(i, Fargs...);
}
template <typename... Targs> static inline void Read_Loop_Digit(int n, Targs*... Fargs) {
	for (int i = 1; i <= n; i++) Read_Loop_Digit_i(i, Fargs...);
	return ;
}

template <typename T> static inline void Read_Loop_P_i(int i, T *a) {return Read_P(a[i]);}
template <typename T, typename... Targs> static inline void Read_Loop_P_i(int i, T *a, Targs*... Fargs) {
	Read_P(a[i]);
	return Read_Loop_P_i(i, Fargs...);
}
template <typename... Targs> static inline void Read_Loop_P(int n, Targs*... Fargs) {
	for (int i = 1; i <= n; i++) Read_Loop_P_i(i, Fargs...);
	return ;
}

// --- Float ---

template <int mul, typename T> static inline void Read(T &n) {
	char c = Get_Raw_Char();
	bool neg = false;
	while (!isdigit(c)) {
		if (c == '-') neg = true;
		c = Get_Raw_Char();
	}
	n = int(c - '0');
	while (isdigit(c = Get_Raw_Char())) n = n * 10 + int(c - '0');
	
	int cnt = 0;

	if (c == '.') {
		while (isdigit(c = Get_Raw_Char())) {
			n = n * 10 + int(c - '0');
			cnt++;
		}
	}

	while (cnt < mul) {
		n = n * 10;
		cnt++;
	}

	if (neg) n = -n;
	return ;
}

template <int mul, typename T> static inline void Read_P(T &n) {
	char c = Get_Raw_Char();
	while (!isdigit(c)) c = Get_Raw_Char();
	
	n = int(c - '0');
	while (isdigit(c = Get_Raw_Char())) n = n * 10 + int(c - '0');
	
	int cnt = 0;

	if (c == '.') {
		while (isdigit(c = Get_Raw_Char())) {
			n = n * 10 + int(c - '0');
			cnt++;
		}
	}

	while (cnt < mul) {
		n = n * 10;
		cnt++;
	}
	return ;
}

template <int mul, typename T, typename... Targs> static inline void Read(T &n, Targs&... Fargs) {
	Read<mul>(n);
	return Read<mul>(Fargs...);
}

template <int mul, typename T, typename... Targs> static inline void Read_P(T &n, Targs&... Fargs) {
	Read_P<mul>(n);
	return Read_P<mul>(Fargs...);
}

// --- cin, cout ---
void IOS() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	return ;
}

// --- freopen ---
void Freopen(const char *in, const char *out) {	
	freopen(in, "r", stdin);
	freopen(out, "w", stdout);
	return ;
}

// --- Output __int128 ---

template <typename T> void Print128(T x) {
	if (x < 0) {
		printf("-");
		x = -x;
	}
	if (x == 0) printf("0");
	else {
		static int val[100];
		int idx = -1;
		while (x) {
			val[++idx] = x % 10;
			x /= 10;
		}
		while (idx >= 0) printf("%d", val[idx--]);
	}
} 

// End of C:\Users\ianli\Desktop\CP\template\Various\Fast_IO\Fast_IO.cpp


// Included from C:\Users\ianli\Desktop\CP\template\Various\Useful_Functions\Useful_Functions.cpp
// --- sort ---
template <typename T> inline void sort(vector<T> &v) {return sort(v.begin(), v.end());}
template <typename T> inline void sort(int n, T *a) {return sort(a + 1, a + n + 1);}
template <typename T> inline void sort_r(vector<T> &v) {return sort(v.begin(), v.end(), greater<T>());}
template <typename T> inline void sort_r(int n, T *a) {return sort(a + 1, a + n + 1, greater<T>());}

// --- Merge ---
template <typename T> inline void Merge_Vec(vector<T> &a, vector<T> &b, vector<T> &c) {
	if (c.size() < a.size() + b.size()) c.resize(a.size() + b.size());
	merge(a.begin(), a.end(), b.begin(), b.end(), c.begin());
	return ;
}

// --- Discrete ---
template <typename T> inline void Discrete(vector<T> &v) {
	sort(v);
	v.resize(unique(v.begin(), v.end()) - v.begin());
	return ;
}

// --- Relabel ---
template <typename T> inline void relabel(int n, T *val, T *dist) {
	if (!dist) dist = val;
	T *tmp = new T[n + 1];
	memcpy(tmp, val, sizeof(T) * (n + 1));
	sort(n, tmp);
	int sz = unique(tmp + 1, tmp + n + 1) - (tmp + 1);
	for (int i = 1; i <= n; i++) dist[i] = lower_bound(tmp + 1, tmp + sz + 1, val[i]) - tmp;
	delete tmp;
	return ;
}

// --- PQ ---
template <typename T> using PQ = priority_queue<T>;
template <typename T> using PQ_R = priority_queue<T, vector<T>, greater<T>>;

// --- misc ---

template <typename T> inline T ABS(T n) {return n >= 0 ? n : -n;}
template <typename T> inline T gcd(T a, T b) {return b ? gcd(b, a % b) : a;}
template <typename T> inline T lcm(T a, T b) {return a * b / gcd(a, b);}
template <typename T> inline T mex(T a, T b) {return (a == 0 || b == 0) ? ((a == 1 || b == 1) ? 2 : 1) : 0;}
template <typename T> inline void chmin(T &a, T b) {
	a = min(a, b);
	return ;
}
template <typename T> inline void chmax(T &a, T b) {
	a = max(a, b);
	return ;
}
// End of C:\Users\ianli\Desktop\CP\template\Various\Useful_Functions\Useful_Functions.cpp


// Included from C:\Users\ianli\Desktop\CP\template\Various\Debug\Debug.cpp
void print(const int &x) {printf("%d", x);}
void print(const long long int &x) {printf("%lld", x);}
void print(const double &x) {printf("%.20lf", x);}
void print(const char *x) {printf("%s", x);}

void print(const int n, const int *x) {
	printf("%d", x[1]); for (int i = 2; i <= n; i++) printf(" %d", x[i]); printf("\n");
	return ;
}

void print(const int n, const long long int *x) {
	printf("%lld", x[1]); for (int i = 2; i <= n; i++) printf(" %lld", x[i]); printf("\n");
	return ;
}
// End of C:\Users\ianli\Desktop\CP\template\Various\Debug\Debug.cpp


// Included from C:\Users\ianli\Desktop\CP\template\Math\Mod_Int\Mod_Int.cpp
template <typename T> T Pow(T a, long long int b) {
	T ans(1);
	while (b) {
		if (b & 1) ans *= a;
		a *= a;
		b >>= 1;
	}
	return ans;
}

template <int kMod> struct Mod_Int {
	constexpr static int Mod() {return kMod;}

	long long int val;
	Mod_Int() {val = 0;}
	template <typename T> Mod_Int(T x) {val = x;}
	template <int nMod> Mod_Int(Mod_Int<nMod> x) {val = x.val % kMod;}

	Mod_Int inv() const {return Pow(*this, kMod - 2);} 

	Mod_Int operator + (const Mod_Int &x) const {
		Mod_Int ans(val + x.val);
		if (ans.val >= kMod) ans.val -= kMod;
		return ans;
	}
	Mod_Int operator - (const Mod_Int &x) const {
		Mod_Int ans(val - x.val);
		if (ans.val < 0) ans.val += kMod;
		return ans;
	}
	Mod_Int operator * (const Mod_Int &x) const {return Mod_Int(val * x.val % kMod);}
	Mod_Int operator / (const Mod_Int &x) const {return *this * x.inv();}
	Mod_Int operator ^ (const Mod_Int &x) const {return Pow(*this, x.val);}
	Mod_Int operator << (const int &x) const {return (val << x) % kMod;}

	Mod_Int operator += (const Mod_Int &x) {
		val += x.val;
		if (val >= kMod) val -= kMod;
		return *this;
	}
	Mod_Int operator -= (const Mod_Int &x) {
		val -= x.val;
		if (val < 0) val += kMod;
		return *this;
	}
	Mod_Int operator *= (const Mod_Int &x) {
		val = val * x.val % kMod;
		return *this;
	}
	Mod_Int operator /= (const Mod_Int &x) {
		val = val * x.inv().val % kMod;
		return *this;
	}
	Mod_Int operator ^= (const Mod_Int &x) {
		val = Pow(*this, x.val).val;
		return *this;
	}
	Mod_Int operator <<= (const int &x) {
		val = (val << x) % kMod;
		return *this;
	}

	Mod_Int operator ++(int) {
		val++;
		if (val >= kMod) val -= kMod;
		return *this;
	}
	Mod_Int operator --(int) {
		val--;
		if (val < 0) val += kMod;
		return *this;
	}

	bool operator == (const Mod_Int &x) const {return val == x.val;}
	bool operator != (const Mod_Int &x) const {return val != x.val;}
};

using Mint = Mod_Int<kMod>;

namespace Factorial {
	Mint *f, *inf;
	bool preprocessed_factorial;
	void Pre_Factorial(const int &sz) {
		if (preprocessed_factorial) return ;
		preprocessed_factorial = true;
		f = new Mint[sz + 1];
		inf = new Mint[sz + 1];
		f[0] = f[1] = inf[0] = inf[1] = 1;
		for (int i = 2; i <= sz; i++) f[i] = f[i - 1] * i;
		inf[sz] = f[sz].inv();
		for (int i = sz; i > 2; i--) inf[i - 1] = inf[i] * i;
		return ;
	}
	inline Mint P(const int &n, const int &m) {return f[n] * inf[m];}
	inline Mint C(const int &n, const int &m) {return f[n] * inf[m] * inf[n - m];}
	inline Mint H(const int &n, const int &m) {return f[n + m - 1] * inf[m] * inf[n - 1];}
	inline Mint Catalan(const int &n) {return f[n << 1] * inf[n] * inf[n + 1];}
}

namespace Factorial_No_Inf {
	Mint *f;
	void Pre_Factorial(const int &sz) {
		f = new Mint[sz + 1];
		f[0] = f[1] = 1;
		for (int i = 2; i <= sz; i++) f[i] = f[i - 1] * i;
		return ;
	}
	inline Mint P(const int &n, const int &m) {return f[n] / f[m];}
	inline Mint C(const int &n, const int &m) {return f[n] / (f[m] * f[n - m]);}
	inline Mint H(const int &n, const int &m) {return f[n + m - 1] / (f[m] * f[n - 1]);}
	inline Mint Catalan(const int &n) {return f[n << 1] / (f[n] * f[n + 1]);}
}

namespace Inverse {
	using namespace Factorial;
	Mint *inv;
	void Pre_Inverse(const int &sz) {
		inv = new Mint[sz + 1];
		inv[1] = 1;
		Pre_Factorial(sz);
		for (int i = 1; i <= sz; i++) inv[i] = f[i - 1] * inf[i];
		return ;
	}
};
// End of C:\Users\ianli\Desktop\CP\template\Math\Mod_Int\Mod_Int.cpp


// Included from C:\Users\ianli\Desktop\CP\template\Math\NTT\Butterfly.cpp
namespace butterfly_inner {
	int bsf(unsigned int n) {
#ifdef _MSC_VER
		unsigned long index;
		_BitScanForward(&index, n);
		return index;
#else
		return __builtin_ctz(n);
#endif
	}
}

int NTT_size(int size) {return 1 << (__lg(size) + 2);}

template <typename T> void NTT(T *v, int size) {
	assert(size == (size & -size));

	static constexpr int g = 3; // primitive root
	int h = __lg(size);

	static bool first = true;
	static T sum_e[30];
	if (first) {
		first = false;
		T es[30], ies[30];
		int cnt2 = butterfly_inner::bsf(T::Mod() - 1);
		T e = Pow(T(g), (T::Mod() - 1) >> cnt2), ie = e.inv();
		for (int i = cnt2; i >= 2; i--) {
			es[i - 2] = e;
			ies[i - 2] = ie;
			e *= e;
			ie *= ie;
		}
		T now = 1;
		for (int i = 0; i <= cnt2 - 2; i++) {
			sum_e[i] = es[i] * now;
			now *= ies[i];
		}
	}
	for (int ph = 1; ph <= h; ph++) {
		int w = 1 << (ph - 1), p = 1 << (h - ph);
		T now = 1;
		for (int s = 0; s < w; s++) {
			int offset = s << (h - ph + 1);
			for (int i = 0; i < p; i++) {
				auto l = v[i + offset];
				auto r = v[i + offset + p] * now;
				v[i + offset] = l + r;
				v[i + offset + p] = l - r;
			}
			now *= sum_e[butterfly_inner::bsf(~(unsigned int)(s))];
		}
	}
	return ;
}

template <typename T> void NTT_Inv(T *v, int size) {
	assert(size == (size & -size));

	static constexpr int g = 3; // primitive root
	int h = __lg(size);

	static bool first = true;
	static T sum_ie[30];
	if (first) {
		first = false;
		T es[30], ies[30];
		int cnt2 = butterfly_inner::bsf(T::Mod() - 1);
		T e = Pow(T(g), (T::Mod() - 1) >> cnt2), ie = e.inv();
		for (int i = cnt2; i >= 2; i--) {
			es[i - 2] = e;
			ies[i - 2] = ie;
			e *= e;
			ie *= ie;
		}
		T now = 1;
		for (int i = 0; i <= cnt2 - 2; i++) {
			sum_ie[i] = ies[i] * now;
			now *= es[i];
		}
	}

	for (int ph = h; ph >= 1; ph--) {
		int w = 1 << (ph - 1), p = 1 << (h - ph);
		T inow = 1;
		for (int s = 0; s < w; s++) {
			int offset = s << (h - ph + 1);
			for (int i = 0; i < p; i++) {
				T l = v[i + offset];
				T r = v[i + offset + p];
				v[i + offset] = l + r;
				v[i + offset + p] = (l - r) * inow;
			}
			inow *= sum_ie[butterfly_inner::bsf(~(unsigned int)(s))];
		}
	}

	T iz = T(size).inv();
	for (int i = 0; i < size; i++) v[i] *= iz;
	return ;
}
// End of C:\Users\ianli\Desktop\CP\template\Math\NTT\Butterfly.cpp

using namespace Factorial;

Mint A[kN], B[kN];

int main() {
	int n, m, k; RP(n, m, k);
	Pre_Factorial(n);

	int ntt_sz = NTT_size(m);

	for (int i = 0; i * k <= m && i <= n + 1 - m; i++) {
		A[i * k] = C(n + 1 - m, i);
		if (i & 1) A[i * k] = Mint(0) - A[i * k];
	}

	for (int i = 0; i <= m; i++) B[i] = C(i + (n - m), n - m);

	//for (int i = 0; i <= m; i++) printf("A[%d] = %lld\n", i, A[i]);
	//for (int i = 0; i <= m; i++) printf("B[%d] = %lld\n", i, B[i]);

	NTT(A, ntt_sz);
	NTT(B, ntt_sz);

	for (int i = 0; i < ntt_sz; i++) A[i] *= B[i];

	NTT_Inv(A, ntt_sz);

	Mint ans;
	ans = C(n, m) - A[m];
	printf("%lld\n", ans);
}
// End of C.cpp

0