您的位置:首页 > 其它

hdu 2079 选课时间(题目已修改,注意读题) 母函数

2015-08-03 20:17 218 查看
链接:http://acm.hdu.edu.cn/showproblem.php?pid=2079


选课时间(题目已修改,注意读题)

Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 3434 Accepted Submission(s): 2704



Problem Description

又到了选课的时间了,xhd看着选课表发呆,为了想让下一学期好过点,他想知道学n个学分共有多少组合。你来帮帮他吧。(xhd认为一样学分的课没区别)



Input

输入数据的第一行是一个数据T,表示有T组数据。

每组数据的第一行是两个整数n(1 <= n <= 40),k(1 <= k <= 8)。

接着有k行,每行有两个整数a(1 <= a <= 8),b(1 <= b <= 10),表示学分为a的课有b门。



Output

对于每组输入数据,输出一个整数,表示学n个学分的组合数。



Sample Input

2
2 2
1 2
2 1
40 8
1 1
2 2
3 2
4 2
5 8
6 9
7 6
8 8




Sample Output

2
445




突然顿悟了母函数。其实就是模拟来的。第一个东西取几个 的状态 先弄出来,然后接下来就是有新的东西,然后就是新的放一个或者多个 更新进去,然后注意别超过最大值就行了。

//整数拆分模板
#include <iostream>
using namespace std;
const int lmax=1000;
//c1是用来存放展开式的系数的,而c2则是用来计算时保存的,
//他是用下标来控制每一项的位置,比如 c2[3] 就是 x^3 的系数。 
//用c1保存,然后在计算时用c2来保存变化的值。 
int c1[lmax+1],c2[lmax+1];
int aa[20],bb[20];
int main()
{
	int n;
	int sum; 
	int t;
	scanf("%d",&t);
	while (t--)
	{ 
		scanf ("%d%d",&sum,&n);
		for(int i=1;i<=n;i++)
		{
			scanf("%d%d",aa+i,bb+i);
		}
		for(int i=0; i<=sum; i++ )
		{
			c1[i]=0;
			c2[i]=0;
		}
		if(n)
		for(int i=0;i<=bb[1];i++)
		{
			if(aa[1]*i<=sum)
				c1[aa[1]*i]=1;
		} 
		for (int i=2; i<=n; i++)
		{
			for (int j=0; j<=sum; j++ )
			{
				for (int k=0; k<=bb[i]; k++ )
				{ 
					if(j+k*aa[i]<=sum)
					c2[j+k*aa[i]]+=c1[j];
				}		
			}
			for (int j=0; j<=sum; j++ )
			{
				c1[j] = c2[j] ;
				c2[j] = 0 ;
			}
		}
		printf ("%d\n",c1[sum]);
	}
	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: