挑战程序设计竞赛 2.3章习题 poj 3046 Ant Counting

https://vjudge.net.cn/problem/POJ-3046#author=GPT_zh

有一天,贝西在蚂蚁山里探头探脑,看着蚂蚁们来来回回地觅食。
她发现很多蚂蚁都是兄弟姐妹,彼此无法区分。
她还发现,有时只有一只蚂蚁去觅食,有时几只,有时全部。
这就产生了大量不同组合的蚂蚁!

有点数学天赋的贝茜开始琢磨起来。贝西注意到,蜂巢里有 T1 <= T <= 1,000)个蚂蚁家庭,
她把它们标为 1...T(共有 A 只蚂蚁)。
每个家庭有一定数量的蚂蚁 Ni (1 <= Ni <= 100)。

可以组成多少个大小为 S、S+1、......、B(1 <= S <= B <= A)的小组?

在观察一个蚂蚁群时,可以看到三个蚂蚁家族的集合是{1, 1, 2, 2, 3},但很少按这个顺序排列。
蚂蚁行进的可能集合是

有 1 只蚂蚁的 3 个集合: {1} {2} {3}2 只蚂蚁的 5{1,1} {1,2} {1,3} {2,2} {2,3}3 只蚂蚁的 5{1,1,2} {1,1,3} {1,2,2} {1,2,3} {2,2,3}4 只蚂蚁的 3{1,2,2,3} {1,1,2,2} {1,1,2,3}5 只蚂蚁的 1{1,1,2,2,3}

你的任务是根据上述数据计算可能的蚂蚁集合数。
输入
*1 行:4 个空格分隔的整数: T、A、S 和 B

*2...A+1 行:每行包含一个整数,即蜂巢中存在的蚂蚁类型
输出
*1 行: 可创建的大小为 S...B(包括 S...B)的集合数量。像 {1,2} 这样的集合与 {2,1} 这样的集合相同,不应重复计算。
只打印该数字的后六位,不打印前导零或空格。

3 5 2 3
1
2
2
1
3

10


提示
输入细节:
三种类型的蚂蚁(1...3);共有 5 只蚂蚁。可以制作多少套大小为 23 的蚂蚁?

输出细节:
5 组有两名成员的蚂蚁;另外 5 组有三名成员的蚂蚁


题意简化一下 就是
1到t组,每组抽出若干数字,总个数为sum的方案数是多少
最后输出 ans
ans =  sum=S方案数 + sum=S+1方案数 + sum=S+2方案数 ~~~~  + sum=B方案数

解答
dp

代码如下:

#include <iostream>

using namespace std;


const int N = 1000 * 100 + 10;
int dp[1000][N];
int ants[N];
int T, S, A, B;
const int MOD = 1000000;

void solve() {
	dp[0][0] = 1;

	for (int i = 1; i <= T; i++) {
		for (int j = 0; j <= A; j++) {
			for (int k = 0; k <= ants[i]; k++) {
				if (j >= k) {
					dp[i][j] += dp[i - 1][j - k];
					dp[i][j] %= MOD;
				}
			}
		}
	}

	long long  ans = 0;
	for (int i = S; i <= B; i++) {
		ans += dp[T][i];
		ans %= MOD;
	}
	cout << ans << endl;

	return;
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);

	cin >> T >> A >> S >> B;

	for (int i = 1; i <= A; i++) {
		int t; cin >> t;
		ants[t]++;
	}

	solve();

	return 0;
}
在POJ能ac 但是可能是数据太弱的原因。
A在极端取值 1000组蚂蚁 每个蚂蚁都是100个。 那么A=100000
上面的代码 耗时就是O(A*T*100) 就是1e10  会超时的。

下面进行优化

#include <iostream>

using namespace std;


const int N = 1000 * 100 + 10;
int dp[1000][N];
int ants[N];
int T, S, A, B;
const int MOD = 1000000;

void solve() {
	dp[0][0] = 1;

	for (int i = 1; i <= T; i++) {
		for (int j = 0; j <= A; j++) {
			if (j == 0) { dp[i][j] = 1; }
			else if (j  >= ants[i]+1) {
				dp[i][j] = dp[i - 1][j] + dp[i][j - 1] - dp[i - 1][j - ants[i]-1];
			}
			else {
				dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
			}
			dp[i][j]  %= MOD;
		}
	
	}

	long long  ans = 0;
	for (int i = S; i <= B; i++) {
		ans += dp[T][i];
		ans = (ans + MOD) % MOD;
	}
	cout << ans << endl;
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);

	cin >> T >> A >> S >> B;

	for (int i = 1; i <= A; i++) {
		int t; cin >> t;
		ants[t]++;
	}

	solve();

	return 0;
}

我的视频题解空间

posted on   itdef  阅读(8)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
历史上的今天:
2021-05-18 《算法竞赛进阶指南》 第二章 Acwing 139. 回文子串的最大长度
2019-05-18 AcWing 803. 区间合并
2019-05-18 AcWing 801. 二进制中1的个数
2019-05-18 AcWing 800. 数组元素的目标和
2019-05-18 AcWing 799. 最长连续不重复子序列
2019-05-18 AcWing 795. 前缀和
2019-05-18 AcWing 791. 高精度加法 解题记录

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

点击右上角即可分享
微信分享提示