AtCoder Regular Contest 160 D Mahjong

洛谷传送门

AtCoder 传送门

搞笑题,我不会做,我更搞笑。

考虑逆序操作,即初始有一个全 \(0\) 序列,每次单点加 \(k\) 或者长为 \(k\) 区间加 \(1\)。考虑把一个操作集合唯一对应到一个最终序列,不难发现只要限制每个区间加 \(1\) 的次数 \(< k\) 即可。因为如果正序操作,加上了限制,每个点被每个区间加的次数能算出来。

于是题目变成了统计序列 \(b_{1 \sim 2n - k + 1}\) 个数,要求:

  • \(\sum\limits_{i=1}^{2n - k + 1} b_i = \frac{m}{k}\)
  • \(\forall i \in [1, n - k + 1], b_i < k\)

这是一个有上界的插板法,容斥,钦定 \(i\) 个元素不合法,其余任意,那我们得到:

\[ans = \sum\limits_{i=0}^{n-k+1} (-1)^i \binom{n-k+1}{i} \binom{\frac{m}{k}-ik+2n-k}{2n-k} \]

暴力计算组合数,时间复杂度 \(O(n^2 \log mod)\)

code
// Problem: D - Mahjong
// Contest: AtCoder - AtCoder Regular Contest 160
// URL: https://atcoder.jp/contests/arc160/tasks/arc160_d
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
#define pb emplace_back
#define fst first
#define scd second
#define mems(a, x) memset((a), (x), sizeof(a))

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef long double ldb;
typedef pair<ll, ll> pii;

const ll mod = 998244353;

inline ll qpow(ll b, ll p) {
	ll res = 1;
	while (p) {
		if (p & 1) {
			res = res * b % mod;
		}
		b = b * b % mod;
		p >>= 1;
	}
	return res;
}

ll n, m, K;

inline ll C(ll n, ll m) {
	if (n < m || n < 0 || m < 0) {
		return 0;
	}
	ll res = 1;
	for (ll i = n; i >= n - m + 1; --i) {
		res = res * (i % mod) % mod;
	}
	for (int i = 1; i <= m; ++i) {
		res = res * qpow(i, mod - 2) % mod;
	}
	return res;
}

void solve() {
	scanf("%lld%lld%lld", &n, &m, &K);
	if (m % K) {
		puts("0");
		return;
	}
	m /= K;
	ll ans = 0;
	for (int i = 0; i <= n - K + 1; ++i) {
		ans = (ans + ((i & 1) ? mod - 1 : 1) * C(n - K + 1, i) % mod * C(m - i * K + n * 2 - K, n * 2 - K) % mod) % mod;
	}
	printf("%lld\n", ans);
}

int main() {
	int T = 1;
	// scanf("%d", &T);
	while (T--) {
		solve();
	}
	return 0;
}

posted @ 2023-05-16 11:35  zltzlt  阅读(132)  评论(0编辑  收藏  举报