转自:Preeee
1.以一个问题为引例:重量为1,3,5g的砝码各两个,可以称出多少种重量不同的物品?
构造母函数G(x)=(1+x+x^2)(1+x^3+x^6)(1+x^5+x^10),其中x的指数表示砝码的重量,x表示砝码。
每个括号里代表的状态是取0个、取1个、取2个。
得到的各个x^n前面的系数就是每种质量可以称出的方案数目。所得式子的个数就代表可以称出多少种的重量。
2.再看另一种情况:重量为1,3,5g的砝码,可以称出某种质量的方案数目是多少?
构造母函数G1(X)=(1+x+x^2+x^3+......)(1+x^3+x^6+x^9+......)(1+x^5+x^10+x^15+......)
若质量为n,则x^n前面的系数就是方案数目。
以一个题为例:1、2、3、4.....元的面值可以组成面值为n的方案数有多少?
超级详细代码加思想:
#include
using namespace std;
const int _max = 10001;
// c1是保存各项质量砝码可以组合的数目
// c2是中间量,保存没一次的情况
int c1[_max], c2[_max];
int main()
{
int nNum; //你想用已有的面值组成nNum大小的面值
int i, j, k;
//该代码的前提是假设所有面值为1、2、3、4、5元.....的连续数,即下面的 i
//数量无限,即每种有无数张,每种可取0、1、2、3、4........
while(cin >> nNum)
{
for(i=0; i<=nNum; ++i) //此时的nNum是第一个括号的所有项个数 // ---- ①
{
c1[i] = 1; //
c2[i] = 0;
}
for(i=2; i<=nNum; ++i) //nNum 括号个数//指向第几个括号 // ----- ②
{//第一个括号已经初始化系数;//可以看出若取钱为num则第num+1个括号用不到
//因为钱数连续为1、2、3、4...元
for(j=0; j<=nNum; ++j) //j是第一个括号里的每一项x^j的指数j
for(k=0; k+j<=nNum; k+=i) //k相隔i; // k第二个括号的每一项x^k的指数
{ //比如说(1+x+x^2+...)(1+x^2+x^4+...)例如用1乘第二个括号内数
//得到数的指数结果为1、2、4;所以k的下一个值就是k+=i
c2[j+k] += c1[j]; //目前的第一括号与第二括号两两相乘
//由于第二括号的系数全为1,相乘后的系数就是c1[j],累加即可
}
for(j=0; j<=nNum; ++j) // 把c2中的值给c1,并把c2清0
{
c1[j] = c2[j];
c2[j] = 0;
}
}
cout << c1[nNum] << endl;//输出能组成nNum大小的方案数
}
return 0;
}
代码参考:https://blog.csdn.net/winter2121/article/details/55535894
当然上面的代码只是一个超级简单的模板,具体题目还要经过一定变动,但是理解了上面代码才能把变式题解决。