BZOJ3193: [JLOI2013]地形生成

本文探讨了一种特定的排列组合问题,涉及到山的高度和数量限制。通过将山按高度从大到小排序,并考虑数量限制,文章提供了解决方案,包括如何处理相同高度的山之间的相互影响。使用动态规划方法,文章详细解释了如何计算不同情况下可能的排列组合数量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

传送门

Sol

第一问可以考虑按照山的高度从大到小放
但是这样如果遇到高度相同的就不好考虑,那么同时要求数量限制从小到大
这样每次放的时候后面的一定不会影响前面,并且高度相同的时候前面能放的位置后面的也能放
直接乘起来就好了
对于第二问,此时高度相同的会有影响
对于高度相同的一段,强制要求数量限制从小到大,并且后面的位置必须小于前面
f i , j f_{i,j} fi,j 表示放了 i i i 个到 j j j 个空位,最后一个放的在最后,的方案数
那么 f i , j = ∑ k ≤ j f i − 1 , k f_{i,j}=\sum_{k\le j}f_{i-1,k} fi,j=kjfi1,k
前缀和优化即可,最后把答案乘起来

# include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int maxn(1005);
const int mod(2011);

struct Hill {
	int h, c;

	inline bool operator < (Hill b) const {
		return (h ^ b.h) ? h > b.h : c < b.c;
	}
} h[maxn];

int n, f[maxn][maxn];

inline int Solve(int l, int r) {
	register int i, j, len = r - l + 1;
	for (i = 0; i <= len; ++i)
		for (j = 0; j <= l; ++j) f[i][j] = 0;
	for (i = 1; i <= l; ++i) f[0][i] = 1;
	for (i = 1; i <= len; ++i) {
		for (j = 1; j <= min(l, h[i + l - 1].c); ++j) f[i][j] = f[i - 1][j];
		for (j = 1; j <= l; ++j) f[i][j] = (f[i][j] + f[i][j - 1]) % mod;
	}
	return f[len][l];
}

int main() {
	register int i, c, ans;
	scanf("%d", &n);
	for (i = 1; i <= n; ++i) scanf("%d%d", &h[i].h, &h[i].c);
	sort(h + 1, h + n + 1);
	for (ans = 1, i = 2, c = 0; i <= n; ++i) {
		c = h[i].h == h[i - 1].h ? c + 1 : 0;
		ans = ans * min(i, h[i].c + c) % mod;
	}
	printf("%d ", ans);
	for (ans = 1, i = 1, c = 0; i <= n; ++i)
		if (i == n || h[i].h != h[i + 1].h) ans = ans * Solve(i - c, i) % mod, c = 0;
		else ++c;
	printf("%d\n", ans);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值