結果

問題 No.2181 LRM Question 2
ユーザー MasKoaTSMasKoaTS
提出日時 2022-08-28 23:51:47
言語 C++17
(gcc 12.3.0 + boost 1.83.0)
結果
AC  
実行時間 747 ms / 2,000 ms
コード長 8,759 bytes
コンパイル時間 1,356 ms
コンパイル使用メモリ 103,180 KB
実行使用メモリ 14,800 KB
最終ジャッジ日時 2024-05-09 21:19:17
合計ジャッジ時間 5,904 ms
ジャッジサーバーID
(参考情報)
judge2 / judge1
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 12 ms
7,936 KB
testcase_01 AC 11 ms
7,936 KB
testcase_02 AC 426 ms
7,936 KB
testcase_03 AC 11 ms
7,936 KB
testcase_04 AC 12 ms
7,936 KB
testcase_05 AC 12 ms
8,064 KB
testcase_06 AC 12 ms
7,936 KB
testcase_07 AC 11 ms
7,936 KB
testcase_08 AC 530 ms
7,936 KB
testcase_09 AC 196 ms
7,936 KB
testcase_10 AC 733 ms
7,936 KB
testcase_11 AC 743 ms
7,936 KB
testcase_12 AC 747 ms
7,936 KB
testcase_13 AC 12 ms
7,936 KB
testcase_14 AC 49 ms
14,800 KB
testcase_15 AC 13 ms
7,936 KB
testcase_16 AC 44 ms
13,136 KB
testcase_17 AC 19 ms
7,936 KB
testcase_18 AC 12 ms
7,936 KB
testcase_19 AC 13 ms
7,936 KB
testcase_20 AC 22 ms
9,468 KB
testcase_21 AC 61 ms
7,936 KB
testcase_22 AC 13 ms
7,936 KB
testcase_23 AC 11 ms
7,936 KB
testcase_24 AC 11 ms
7,936 KB
testcase_25 AC 12 ms
7,936 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

/*
* Copyright (c) 2019 Ryotaro Sato
* All functions and data structures prior to the main function are released under the MIT license.
* https://github.com/hitonanode/cplib-cpp/blob/master/LICENSE
*/

#include <iostream>
#include <algorithm>
#include <cassert>
#include <tuple>
#include <utility>
#include <vector>
#include <map>
using ll = long long;

// CUT begin
// Solve ax+by=gcd(a, b)
template <class Int> Int extgcd(Int a, Int b, Int& x, Int& y) {
	Int d = a;
	if (b != 0) {
		d = extgcd(b, a % b, y, x), y -= (a / b) * x;
	}
	else {
		x = 1, y = 0;
	}
	return d;
}
// Calculate a^(-1) (MOD m) s if gcd(a, m) == 1
// Calculate x s.t. ax == gcd(a, m) MOD m
template <class Int> Int mod_inverse(Int a, Int m) {
	Int x, y;
	extgcd<Int>(a, m, x, y);
	x %= m;
	return x + (x < 0) * m;
}

// Require: 1 <= b
// return: (g, x) s.t. g = gcd(a, b), xa = g MOD b, 0 <= x < b/g
template <class Int> /* constexpr */ std::pair<Int, Int> inv_gcd(Int a, Int b) {
	a %= b;
	if (a < 0) a += b;
	if (a == 0) return { b, 0 };
	Int s = b, t = a, m0 = 0, m1 = 1;
	while (t) {
		Int u = s / t;
		s -= t * u, m0 -= m1 * u;
		auto tmp = s;
		s = t, t = tmp, tmp = m0, m0 = m1, m1 = tmp;
	}
	if (m0 < 0) m0 += b / s;
	return { s, m0 };
}

template <class Int>
/* constexpr */ std::pair<Int, Int> crt(const std::vector<Int>& r, const std::vector<Int>& m) {
	assert(r.size() == m.size());
	int n = int(r.size());
	// Contracts: 0 <= r0 < m0
	Int r0 = 0, m0 = 1;
	for (int i = 0; i < n; i++) {
		assert(1 <= m[i]);
		Int r1 = r[i] % m[i], m1 = m[i];
		if (r1 < 0) r1 += m1;
		if (m0 < m1) {
			std::swap(r0, r1);
			std::swap(m0, m1);
		}
		if (m0 % m1 == 0) {
			if (r0 % m1 != r1) return { 0, 0 };
			continue;
		}
		Int g, im;
		std::tie(g, im) = inv_gcd<Int>(m0, m1);

		Int u1 = m1 / g;
		if ((r1 - r0) % g) return { 0, 0 };

		Int x = (r1 - r0) / g % u1 * im % u1;
		r0 += x * m0;
		m0 *= u1;
		if (r0 < 0) r0 += m0;
	}
	return { r0, m0 };
}

// 蟻本 P.262
// 中国剰余定理を利用して,色々な素数で割った余りから元の値を復元
// 連立線形合同式 A * x = B mod M の解
// Requirement: M[i] > 0
// Output: x = first MOD second (if solution exists), (0, 0) (otherwise)
template <class Int>
std::pair<Int, Int>
linear_congruence(const std::vector<Int>& A, const std::vector<Int>& B, const std::vector<Int>& M) {
	Int r = 0, m = 1;
	assert(A.size() == M.size());
	assert(B.size() == M.size());
	for (int i = 0; i < (int)A.size(); i++) {
		assert(M[i] > 0);
		const Int ai = A[i] % M[i];
		Int a = ai * m, b = B[i] - ai * r, d = std::__gcd(M[i], a);
		if (b % d != 0) {
			return std::make_pair(0, 0); // 解なし
		}
		Int t = b / d * mod_inverse<Int>(a / d, M[i] / d) % (M[i] / d);
		r += m * t;
		m *= M[i] / d;
	}
	return std::make_pair((r < 0 ? r + m : r), m);
}

int pow_mod(int x, long long n, int md) {
	if (md == 1) return 0;
	long long ans = 1;
	while (n > 0) {
		if (n & 1) ans = ans * x % md;
		x = (long long)x * x % md;
		n >>= 1;
	}
	return ans;
}
#line 5 "number/combination.hpp"

// nCr mod m = p^q (p: prime, q >= 1)
// Can be used for n, r <= 1e18, m <= 1e7
// Complexity: O(m) (construction), O(log(n)) (per query)
// https://ferin-tech.hatenablog.com/entry/2018/01/17/010829
struct combination_prime_pow {
	int p, q, m;
	std::vector<int> fac, invfac, ppow;

	long long _ej(long long n) const {
		long long ret = 0;
		while (n) ret += n, n /= p;
		return ret;
	}

	combination_prime_pow(int p_, int q_) : p(p_), q(q_), m(1), ppow{ 1 } {
		for (int t = 0; t < q; ++t) m *= p, ppow.push_back(m);
		fac.assign(m, 1);
		invfac.assign(m, 1);
		for (int i = 1; i < m; ++i) fac[i] = (long long)fac[i - 1] * (i % p ? i : 1) % m;
		invfac[m - 1] = fac[m - 1]; // Same as Wilson's theorem
		assert(1LL * fac.back() * invfac.back() % m == 1);
		for (int i = m - 1; i; --i) invfac[i - 1] = (long long)invfac[i] * (i % p ? i : 1) % m;
	}

	int nCr(long long n, long long r) const {
		if (r < 0 or n < r) return 0;
		if (p == 2 and q == 1) return !((~n) & r); // Lucas
		long long k = n - r;
		long long e0 = _ej(n / p) - _ej(r / p) - _ej(k / p);
		if (e0 >= q) return 0;

		long long ret = ppow[e0];
		if (q == 1) { // Lucas
			while (n) {
				ret = __int128(ret) * fac[n % p] * invfac[r % p] * invfac[k % p] % p;
				n /= p, r /= p, k /= p;
			}
			return (int)ret;
		}
		else {
			if ((p > 2 or q < 3) and (_ej(n / m) - _ej(r / m) - _ej(k / m)) & 1) ret = m - ret;
			while (n) {
				ret = __int128(ret) * fac[n % m] * invfac[r % m] * invfac[k % m] % m;
				n /= p, r /= p, k /= p;
			}
			return (int)ret;
		}
	}
};

// nCr mod m
// Complexity: O(m) space worst (construction), O(log(n) log(m)) (per query)
// Input: pairs of (prime, degree), such as vector<pair<int, int>> and map<int, int>
// https://judge.yosupo.jp/problem/binomial_coefficient
struct combination {
	std::vector<combination_prime_pow> cpps;
	std::vector<int> ms;

	template <class Map> combination(const Map& p2deg) {
		for (auto f : p2deg) {
			cpps.push_back(combination_prime_pow(f.first, f.second));
			ms.push_back(cpps.back().m);
		}
	}

	int operator()(long long n, long long r) const {
		if (r < 0 or n < r) return 0;
		std::vector<int> rs;
		for (const auto& cpp : cpps) rs.push_back(cpp.nCr(n, r));
		return crt(rs, ms).first;
	}
};


struct Sieve {
	std::vector<int> min_factor;
	std::vector<int> primes;
	Sieve(int MAXN) : min_factor(MAXN + 1) {
		for (int d = 2; d <= MAXN; d++) {
			if (!min_factor[d]) {
				min_factor[d] = d;
				primes.emplace_back(d);
			}
			for (const auto& p : primes) {
				if (p > min_factor[d] or d * p > MAXN) break;
				min_factor[d * p] = p;
			}
		}
	}
	// Prime factorization for 1 <= x <= MAXN^2
	// Complexity: O(log x)		   (x <= MAXN)
	//			 O(MAXN / log MAXN) (MAXN < x <= MAXN^2)
	template <class T> std::map<T, int> factorize(T x) const {
		std::map<T, int> ret;
		assert(x > 0 and
			x <= ((long long)min_factor.size() - 1) * ((long long)min_factor.size() - 1));
		for (const auto& p : primes) {
			if (x < T(min_factor.size())) break;
			while (!(x % p)) x /= p, ret[p]++;
		}
		if (x >= T(min_factor.size())) ret[x]++, x = 1;
		while (x > 1) ret[min_factor[x]]++, x /= min_factor[x];
		return ret;
	}
	// Enumerate divisors of 1 <= x <= MAXN^2
	// Be careful of highly composite numbers https://oeis.org/A002182/list
	// https://gist.github.com/dario2994/fb4713f252ca86c1254d#file-list-txt (n, (# of div. of n)):
	// 45360->100, 735134400(<1e9)->1344, 963761198400(<1e12)->6720
	template <class T> std::vector<T> divisors(T x) const {
		std::vector<T> ret{ 1 };
		for (const auto p : factorize(x)) {
			int n = ret.size();
			for (int i = 0; i < n; i++) {
				for (T a = 1, d = 1; d <= p.second; d++) {
					a *= p.first;
					ret.push_back(ret[i] * a);
				}
			}
		}
		return ret; // NOT sorted
	}
	// Euler phi functions of divisors of given x
	// Verified: ABC212 G https://atcoder.jp/contests/abc212/tasks/abc212_g
	// Complexity: O(sqrt(x) + d(x))
	template <class T> std::map<T, T> euler_of_divisors(T x) const {
		assert(x >= 1);
		std::map<T, T> ret;
		ret[1] = 1;
		std::vector<T> divs{ 1 };
		for (auto p : factorize(x)) {
			int n = ret.size();
			for (int i = 0; i < n; i++) {
				ret[divs[i] * p.first] = ret[divs[i]] * (p.first - 1);
				divs.push_back(divs[i] * p.first);
				for (T a = divs[i] * p.first, d = 1; d < p.second; a *= p.first, d++) {
					ret[a * p.first] = ret[a] * p.first;
					divs.push_back(a * p.first);
				}
			}
		}
		return ret;
	}
	// Moebius function Table, (-1)^{# of different prime factors} for square-free x
	// return: [0=>0, 1=>1, 2=>-1, 3=>-1, 4=>0, 5=>-1, 6=>1, 7=>-1, 8=>0, ...] https://oeis.org/A008683
	std::vector<int> GenerateMoebiusFunctionTable() const {
		std::vector<int> ret(min_factor.size());
		for (unsigned i = 1; i < min_factor.size(); i++) {
			if (i == 1) {
				ret[i] = 1;
			}
			else if ((i / min_factor[i]) % min_factor[i] == 0) {
				ret[i] = 0;
			}
			else {
				ret[i] = -ret[i / min_factor[i]];
			}
		}
		return ret;
	}
	// Calculate [0^K, 1^K, ..., nmax^K] in O(nmax)
	// Note: **0^0 == 1**
	template <class MODINT> std::vector<MODINT> enumerate_kth_pows(long long K, int nmax) const {
		assert(nmax < int(min_factor.size()));
		assert(K >= 0);
		if (K == 0) return std::vector<MODINT>(nmax + 1, 1);
		std::vector<MODINT> ret(nmax + 1);
		ret[0] = 0, ret[1] = 1;
		for (int n = 2; n <= nmax; n++) {
			if (min_factor[n] == n) {
				ret[n] = MODINT(n).pow(K);
			}
			else {
				ret[n] = ret[n / min_factor[n]] * ret[min_factor[n]];
			}
		}
		return ret;
	}
};


/*
* Main Code
*/

int main(void) {
	ll l, r, m;  std::cin >> l >> r >> m;
	combination nCr(Sieve(1 << 20).factorize(m));

	ll ans = 0;
	for (ll i = l; i <= r; i++) {
		ans += (ll)nCr(2 * i, i) + m - 2ll;
		ans %= m;
	}
	std::cout << ans << std::endl;

	return 0;
}
0