Ant Counting POJ - 3046

本文深入探讨了多重集组合数问题,通过动态规划方法解决蚂蚁按特定数量组队的组合数计算。给出了清晰的递推公式及代码实现,适合算法初学者及竞赛选手参考。

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

给出T个蚂蚁种类,一共A只蚂蚁,要求算出蚂蚁按照S只到B只组队的组合数

Sample Input

3 5 2 3
1
2
2
1
3

Sample Output

10

思路:多重集组合数问题,dp[i][j] = i 种蚂蚁按照 j 只排列的组合总数

           if(j-1-a[i] >= 0)  dp[i][j] = dp[i][j-1] + dp[i-1][j] -dp[i-1][j-1-a[i]]

           else   dp[i][j] = dp[i][j-1] + dp[i-1][j]

           递推式推导:为了从i 种蚂蚁取出 j 只排列组合 可以 从i-1种蚂蚁取出j-k只排列组合后,从第 i 中蚂蚁中取出k只组合

           dp[i][j] = min(j,a[i])  ∑ k=0   dp[i-1][j-k]            // ∑前是上界,∑后是下界    理解哈

           min(j,a[i])  ∑ k=0   dp[i-1][j-k]   =   ( min(j-1,a[i])  ∑ k=0   dp[i-1][j-k] ) +  dp[i-1][j] - dp[i-1][j-1-a[i]]

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <stdlib.h>
#include <vector>
#include <queue>
#include <cmath>
#include <stack>
#include <map>
#include <fstream>
#include <set>
const long long MAX = 1e5+10;
#define INF 10000000
const int mod = 1e6;

using namespace std;

int dp[1010][MAX]; //前i种取j个的组合数
 
//测试函数 
int main(){
	/*ifstream cin ("D:\\钢铁程序员\\程序数据\\053蚂蚁分队.txt");//从文件读取数据流,省去手动输入的麻烦 
	if(!cin){//读取如果失败 
		cout << "ERROR" << endl;
	}*/
	int T,A,S,B;
	int a[MAX]; //统计蚂蚁集合的数量 
	cin >> T >> A >> S >> B;
	for(int i=0; i<A; i++){
		int c;
		cin >> c;
		a[c]++;
	}
	int ans = 0;
	//依次求出分为S。。B小队的组合数 
	for(int i = 0; i <= T; ++i)
        dp[i][0] = 1;
	for(int i=1; i<=T; i++)
		for(int j=1; j<=A; j++){
			if(j-1-a[i] >= 0)
				dp[i][j] = (dp[i][j-1] + dp[i-1][j] -dp[i-1][j-1-a[i]]+mod)%mod;
			else
				dp[i][j] = (dp[i][j-1] + dp[i-1][j]+mod)%mod;
		}
	for(int i=S; i<=B; i++)
		ans = (ans+dp[T][i]+mod)%mod;
	cout << ans << endl;
	//cin.close();//打开文件以后要关闭 
	return 0;
} 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值