链接: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门。
每组数据的第一行是两个整数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;
}