Submission #70656308


Source Code Expand

#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
#define rep(i, j, k) for(int i = (j); i <= (k); i++)
#define per(i, j, k) for(int i = (j); i >= (k); i--)
#define pb emplace_back
#define fi first
#define se second
using vi = vector<int>;
using pi = pair<int, int>;

template<typename T0, typename T1> bool chmin(T0 &x, const T1 &y){
	if(y < x){x = y; return true;} return false;
}
template<typename T0, typename T1> bool chmax(T0 &x, const T1 &y){
	if(x < y){x = y; return true;} return false;
}

template<typename T> void debug(char *s, T x){
	cerr << s <<" = "<< x <<endl;
}
template<typename T, typename ...Ar> void debug(char *s, T x, Ar... y){
	int dep = 0;
	while(!(*s == ',' && dep == 0)){
		if(*s == '(') dep++;
		if(*s == ')') dep--;
		cerr << *s++;
	}
	cerr <<" = "<< x <<",";
	debug(s + 1, y...);
}
#define gdb(...) debug((char*)#__VA_ARGS__, __VA_ARGS__)

using u32 = uint32_t;
using u64 = uint64_t;
constexpr int mod = 998244353;
struct mint{
	u32 x;
	
	mint(): x(0){}
	mint(int _x){
		_x %= mod;
		if(_x < 0) _x += mod;
		x = _x;
	}

	u32 val()const {
		return x;
	}
	mint qpow(int y = mod - 2)const {
		assert(y >= 0);
		mint t = *this, res = 1;
		while(y){
			if(y % 2) res *= t;
			t *= t;
			y /= 2;
		}
		return res;
	}

	mint& operator += (const mint &B){
		if((x += B.x) >= mod) x -= mod;
		return *this;
	}
	mint& operator -= (const mint &B){
		if((x -= B.x) >= mod) x += mod;
		return *this;
	}
	mint& operator *= (const mint &B){
		x = (u64)x * B.x % mod;
		return *this;
	}
	mint& operator /= (const mint &B){
		return *this *= B.qpow();
	}
	friend mint operator + (const mint &A, const mint &B){
		return mint(A) += B;
	}
	friend mint operator - (const mint &A, const mint &B){
		return mint(A) -= B;
	}
	friend mint operator * (const mint &A, const mint &B){
		return mint(A) *= B;
	}
	friend mint operator / (const mint &A, const mint &B){
		return mint(A) /= B;
	}
	mint operator - ()const {
		return mint() - *this;
	}
};

constexpr int LG = 21, S = 1 << LG;
vector<mint> P, fac, ifac, iv, ip2;

auto INIT = [](){
	P.resize(S);
	rep(i, 0, LG - 1){
		mint stp = mint(3).qpow(mod >> (i + 1));
		P[1 << i] = 1;
		rep(j, (1 << i) + 1, (2 << i) - 1){
			P[j] = P[j - 1] * stp;
		}
	}

	fac.resize(S);
	ifac.resize(S);
	iv.resize(S);
	fac[0] = iv[0] = 1;
	rep(i, 1, S - 1){
		fac[i] = fac[i - 1] * i;
	}
	ifac[S - 1] = 1 / fac[S - 1];
	per(i, S - 1, 1){
		ifac[i - 1] = ifac[i] * i;
		iv[i] = ifac[i] * fac[i - 1];
	}

	ip2.resize(LG + 1);
	ip2[0] = 1;
	rep(i, 1, LG){
		ip2[i] = ip2[i - 1] / 2;
	}
	
	return true;
}();

struct poly : vector<mint>{
	using vector<mint>::vector;
	
	void DIF(int lg){
		for(int i = 1 << (lg - 1); i ; i /= 2){
			for(int j = 0; j < (1 << lg); j += 2 * i){
				rep(k, 0, i - 1){
					mint A = (*this)[j + k], B = (*this)[j + k + i];
					(*this)[j + k] = A + B, (*this)[j + k + i] = (A - B) * P[i + k];
				}
			}
		}
	}

	void DIT(int lg){
		for(int i = 1; i < (1 << lg); i *= 2){
			for(int j = 0; j < (1 << lg); j += 2 * i){
				rep(k, 0, i - 1){
					mint A = (*this)[j + k], B = (*this)[j + k + i] * P[i + k];
					(*this)[j + k] = A + B, (*this)[j + k + i] = A - B;
				}
			}
		}
		reverse(this -> begin() + 1, this -> end());
	}

	friend poly der(const poly &A){
		poly res = A;
		rep(i, 1, (int)res.size() - 1){
			res[i - 1] = res[i] * i;
		}
		res.pop_back();
		return res;
	}

	friend poly ints(const poly &A){
		poly res = A;
		res.pb();
		per(i, (int)res.size() - 1, 0){
			res[i] = res[i - 1] * iv[i];
		}
		res[0] = 0;
		return res;
	}

	poly& operator += (const poly &B){
		if(B.size() > this -> size()){
			this -> resize(B.size());
		}
		rep(i, 0, (int)B.size() - 1){
			(*this)[i] += B[i];
		}
		return *this;
	}

	friend poly operator + (const poly &A, const poly &B){
		return poly(A) += B;
	}

	poly& operator -= (const poly &B){
		if(B.size() > this -> size()){
			this -> resize(B.size());
		}
		rep(i, 0, (int)B.size() - 1){
			(*this)[i] -= B[i];
		}
		return *this;
	}

	friend poly operator - (const poly &A, const poly &B){
		return poly(A) -= B;
	}

	friend poly operator * (const mint &k, const poly &A){
		poly res = A;
		for(auto &x:res) x *= k;
		return res;
	}

	poly& operator *= (const poly &B){
		auto sz = this -> size();
		*this = conv(*this, B);
		this -> resize(sz);
		return *this;
	}

	friend poly operator * (const poly &A, const poly &B){
		return poly(A) *= B;
	}

	poly& operator /= (const poly &B){
		auto sz = this -> size();
		*this = conv(*this, inv(B));
		this -> resize(sz);
		return *this;
	}

	friend poly operator / (const poly &A, const poly &B){
		return poly(A) /= B;
	}

	friend poly conv(const poly &_A, const poly &_B){
		if(_A.size() <= 64 || _B.size() <= 64){
			poly res(_A.size() + _B.size() - 1);
			rep(i, 0, (int)_A.size() - 1){
				rep(j, 0, (int)_B.size() - 1){
					res[i + j] += _A[i] * _B[j];
				}
			}
			return res;
		}

		poly A = _A, B = _B;
		int len = A.size() + B.size() - 1;
		int lg = __lg(len * 2 - 1);
		A.resize(1 << lg), B.resize(1 << lg);
		A.DIF(lg), B.DIF(lg);
		rep(i, 0, (1 << lg) - 1){
			A[i] *= B[i];
		}
		A.DIT(lg);
		A.resize(len);
		for(auto &x:A) x *= ip2[lg];
		return A;
	}

	friend poly inv(const poly &A){
		assert(A[0].val() != 0);
		poly res{mint(1) / A[0]};
		while(res.size() < A.size()){
			int n = res.size(), lg = __lg(n * 4);
			poly buf(1 << lg);
			copy(res.begin(), res.end(), buf.begin());
			buf.DIF(lg);

			poly tmp{A.begin(), A.begin() + min(n * 2, (int)A.size())};
			tmp.resize(n * 4);
			tmp.DIF(lg);
			rep(i, 0, n * 4 - 1) tmp[i] *= buf[i] * buf[i];
			tmp.DIT(lg);

			res.resize(n * 2);
			rep(i, 0, n * 2 - 1){
				res[i] = 2 * res[i] - tmp[i] * ip2[lg];
			}
		}
		res.resize(A.size());
		return res;
	}


	// O(n \log^2 n)
	friend poly exp(const poly &A){
		assert(A[0].val() == 0);
		int n = A.size();
		int lg = __lg(n * 2 - 1);

		poly a = A, res(A.size());
		rep(i, 0, (int)a.size() - 1) a[i] *= i;
		a.resize(1 << lg);

		vector<poly> pre(lg + 1);
		rep(i, 8, lg){
			pre[i].insert(pre[i].end(), a.begin(), a.begin() + (1 << i));
			pre[i].DIF(i);
		}

		res[0] = 1;
		auto slv = [&](auto &self, int l, int r)->void {
			if(r - l <= 128){
				rep(i, l, r - 1){
					rep(j, l, i - 1){
						res[i] += res[j] * a[i - j];
					}
					if(i > 0) res[i] *= iv[i];
				}
				return;
			}
			int mid = (l + r) / 2;
			self(self, l, mid);

			int _lg = __lg((r - l) * 2 - 1);
			poly tmp(res.begin() + l, res.begin() + mid);
			tmp.resize(1 << _lg);
			tmp.DIF(_lg);
			rep(i, 0, (1 << _lg) - 1) tmp[i] *= pre[_lg][i];
			tmp.DIT(_lg);
			rep(i, mid, r - 1) res[i] += tmp[i - l] * ip2[_lg];
			self(self, mid, r);
		};
		slv(slv, 0, n);
		return res;
	}
	
	friend poly ln(const poly &A){
		assert(A[0].val() == 1);
		poly res = der(A) / A;
		return ints(res);
	}
	
	friend poly sqrt(const poly &A){
		assert(A[0].val() == 1);
		return exp(ip2[1] * ln(A));
	}

	friend poly qpow(const poly &A, mint k){
		if(k.val() == 0){
			poly res(A.size());
			res[0] = 1;
			return res;
		}

		auto it = A.begin();
		while(it != A.end() && it -> val() == 0){
			it ++;
		}
		int len = (it - A.begin()) * k.val();
		if(len >= (int)A.size()){
			return poly(A.size());
		} else{
			poly a{it, it + (A.size() - len)};
			mint t = a[0].qpow(k.val());
			a = t * exp(k * ln(1 / a[0] * a));
			a.insert(a.begin(), len, mint());
			return a;
		}
	}
};



signed main(){
	#ifdef LOCAL
	assert( freopen(".in", "r", stdin) );
	assert( freopen(".out", "w", stdout) );
	#endif
	ios::sync_with_stdio(0);
	cin.tie(0);

	int n, m, s;
	cin >> n >> m >> s;
	poly f(s + 1);
	rep(i, 0, min(m, s)){
		f[i] = 1;
	}
	cout << qpow(f, n)[s].val() <<'\n';
}

Submission Info

Submission Time
Task C - Sequence
User bananabot
Language C++ 20 (gcc 12.2)
Score 3
Code Size 7998 Byte
Status AC
Exec Time 252 ms
Memory 46696 KiB

Judge Result

Set Name Sample All
Score / Max Score 0 / 0 3 / 3
Status
AC × 2
AC × 9
Set Name Test Cases
Sample 00_sample_00.txt, 00_sample_01.txt
All 00_sample_00.txt, 00_sample_01.txt, 01_random_00.txt, 01_random_01.txt, 02_m_small_00.txt, 02_m_small_01.txt, 02_m_small_02.txt, 03_max_00.txt, 04_min_00.txt
Case Name Status Exec Time Memory
00_sample_00.txt AC 40 ms 35680 KiB
00_sample_01.txt AC 136 ms 41120 KiB
01_random_00.txt AC 138 ms 41356 KiB
01_random_01.txt AC 249 ms 46480 KiB
02_m_small_00.txt AC 251 ms 46696 KiB
02_m_small_01.txt AC 251 ms 46556 KiB
02_m_small_02.txt AC 251 ms 46660 KiB
03_max_00.txt AC 252 ms 46580 KiB
04_min_00.txt AC 40 ms 35764 KiB