这是一题很典型的母函数的题,母函数我的博客中http://blog.csdn.net/hhq420684/article/details/12876993说的很明白,主要有两种,一种就是我们是说的有限的物体,一种就是无限的东西,那么我们这一题是很明显的有限的题目。其实这一题和1085是很像的,只要1085可以做的出的这一题就可以,因为两者的方法是差不多的。只是有一个数量范围的不同而已。下面就说说这两题的解题思路。
2079是中文题大家应该都明白吧。这个我就不说了。那么下面就是思路。
我们知道这种题是利用多项式来做的,那么就直接说了。
还是和母函数将的差不多我们有两个式子
for(j=0;j<。。;j++)
for(k=0;k<....;k....)
在无限中就是k加的就是最前面的i说的就是在每一个多项式的内部每个式子的系数是相差i的但是这里不是,这里的系数不一定是连续的,所以我们的系数就不能再单纯的这样计算,而是要按照题目中给的来计算,设数组a[10]储存的是学分,b[10]储存的是数量,那么我们最后的k依次增加的量就是a[i],这里的i就是从0到你输入的数量n(n是学分的总类)减去1,那么这里的k小于多少呢,这是个问题,先放一放我们先来看看j,j就是某一个固定的式子的第几项(这里的项数和次数相关,前面已讲过),所以我们的想法是,先计算前面的额,再计算后面的,比如(1+x)(1+x)(1+x^2)我们先计算(1+x)(1+x)就是(1+2x+x^2)那么这时候j就是(1+2x+x^2)里面的指向,所以j的最大值就是两项最大次数的相加,同理到后面后就是前面所有的最大次数的相加,因此j的范围就解决了,下面再看看k,k就是整个的增量,也就是说这个时候k的值就是(1+x)(1+x)(1+x^2)中最大的,为什么?因为这时候我们就已经计算了(1+x)(1+x)他的值,下面的计算是轮到了(1+2x+x^2),所以k的最大值就是最大值就是下面式子的次数最大项(如果有多个还要相乘,因为这个是再一次的轮回中计算的)。
所以就有下面的代码所示的式子:
#include<iostream> using namespace std; int main() { int a[10],b[15],c1[1000],c2[1000]; int N; int n,k,m,i,j,s,t,sum,num; cin>>N; while(N--) { cin>>m>>n; num=0; t=0; sum=0; s=0; for(i=0;i<1000;i++) { c1[i]=0; c2[i]=0; } for(i=0;i<n;i++) { cin>>a[i]>>b[i]; // sum+=a[i]*b[i]; //s+=b[i]; } for(i=0;i<=b[0];i++) c1[i]=1; for(i=0;i<n-1;i++) { num+=a[i]*b[i]; for(j=0;j<=num;j++) for(k=0;k<=b[i+1]*a[i+1];k+=a[i+1]) c2[k+j]+=c1[j]; t=num+a[i+1]*b[i+1]; 这里的t就是前面num的和就是前面计算的所有的式子(一个括号内的)最大项的加。 for(j=0;j<=t;j++) { c1[j]=c2[j]; c2[j]=0; } } cout<<c1[m]<<endl; } return 0; }