组合数与生成母函数

参考:
http://blog.csdn.net/xiaofei_it/article/details/17042651
母函数与排列组合:
https://www.cnblogs.com/dolphin0520/archive/2012/11/07/2755080.html

生成函数模板,计算组合数

// n1为最少数量数组,n2为最大数量数组,v为权值,p为最大值
//为计算结果,b为中间结果。  
int a[MAX],b[MAX];  
//初始化a  
memset(a,0,sizeof(a));  
a[0]=1;  
for (int i=1;i<=17;i++)//循环每个因子  
{  
    memset(b,0,sizeof(b));  
    for (int j=n1[i];j<=n2[i]&&j*v[i]<=P;j++)//循环每个因子的每一项  
        for (int k=0;k+j*v[i]<=P;k++)//循环a的每个项  
            b[k+j*v[i]]+=a[k];//把结果加到对应位, x^k * x^(j*v[i]) = x^(k+j*v[i])
    memcpy(a,b,sizeof(b));//b赋值给a  
}  

计算组合数模版2

//初始化a,因为有last,所以这里无需初始化其他位  
a[0]=1;  
int last=0;  
for (int i=0;i<K;i++)  
{  
    int last2=min(last+n[i]*v[i],P);//计算下一次的last  
    memset(b,0,sizeof(int)*(last2+1));//只清空b[0..last2]  
    for (int j=n1[i];j<=n2[i]&&j*v[i]<=last2;j++)//这里是last2  
        for (int k=0;k<=last&&k+j*v[i]<=last2;k++)//这里一个是last,一个是last2  
            b[k+j*v[i]]+=a[k];  
    memcpy(a,b,sizeof(int)*(last2+1));//b赋值给a,只赋值0..last2  
    last=last2;//更新last  
}  

生成函数题集
https://blog.csdn.net/consciousman/article/details/77935700
一、hdu 1085和hdu 1171两题套用了第二个模板,省略了代码中二三层循环里关于last2的条件(其实也可以加上)。

详见:

hdu 1085:http://blog.csdn.net/xiaofei_it/article/details/17041467

hdu 1171:http://blog.csdn.net/xiaofei_it/article/details/17041709

二、hdu 1398套用了第一个模板,因为n2中每一项为无穷大,所以n2数组就省略了。

详见:

hdu 1398:http://blog.csdn.net/xiaofei_it/article/details/17041815

三、hdu 2079、hdu 2082和hdu 2110三题直接套用了第二个模板。

详见:

hdu 2079:http://blog.csdn.net/xiaofei_it/article/details/17042045

hdu 2082:http://blog.csdn.net/xiaofei_it/article/details/17042253

hdu 2110:http://blog.csdn.net/xiaofei_it/article/details/17042421

另外,至于什么时候用第一个模板,什么时候用第二个模板,就看题目规模。

通常情况下,第一个模板就够用了,上面的那些用第二个模板的题目用第一个模板同样能AC。

但如果数据规模比较大(通常不会有这种情况),就要使用第二个模板了。

以上题目n1均为0。

四、hdu 2152是一道n1不为0的题目,我在这里分别套用第一个和第二个模板解题。

详见:

hdu 2152:http://blog.csdn.net/xiaofei_it/article/details/17042497

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值