母函数~指数型
指数型的母函数用于解决多重集的排列组合问题。
数字拆分:即把整数分解成若干整数的和
#include <iostream> #include <cstdio> using namespace std; const int maxn=150; int c1[maxn], c2[maxn]; void first(){ int i, j, k; //模拟手算方式计算一个括号一个括号计算 for(i=0; i<=120; i++){//初始化c1,c2数组 c1[i]=1;//c1数组记录的是当前已经合并的项的系数(c1初始化为1,第一项系数都为1)
c2[i]=0; // c2记录下一次计算出的值 } for(i=2; i<=120; i++) {//从函数第二个括号开始计算 for(j=0; j<=120; j++) { //每个括号的每一项,都要与前一个小括号里面的每一项计算。 if(c1[j]){ //判断当前项系数是否存在,不存在没必要算,节省很多时间 for(k=0; k+j<=120; k+=i){//控制每一项里面 X 增加的比例 c2[j+k]+=c1[j];// 合并同类项,他们的系数要加在一起 } } } for(j=0; j<=120; j++) { // 刷新一下数据,继续下一次计算,就是下一个括号里面的每一项。 c1[j]=c2[j]; c2[j]=0; } } } int main(){ first(); int n; while(scanf("%d", &n)!= EOF){ printf("%d\n", c1[n]); } return 0; }
大意:有一台天平,输出你不能称量的重量。(天平两个托盘放东西时, 相当于减)
//c数组记录的是砝码的重量 //a数组记录最终计算式的个项系数 //b数组是临时数组 for(i=0; i<=c[0]; i+=c[0]){//计算第一个括号的系数 a[i]=1; } for(i=1; i<n; i++) { for(j=0; j<=sum; j++) { if(a[j]){ for(k=0; k<=c[i]; k+=c[i]) { b[j+k] += a[j]; //指数和的结果 b[(int)abs(j-k)] += a[j]; //这里计算了指数差的结果 } } } for(j=0; j<=sum; j++){ a[j]=b[j]; b[j]=0; } } for(j=0, i=0; i<=sum; i++){ //d数组保存不能计算的数值 if(a[i]== 0){ d[j++]=i; } }
题意很清楚,每一项多了一个最多最少的约束条件
memset(a, 0, sizeof(a)); memset(b, 0, sizeof(b)); for(i=c[0][0]; i<=c[0][1]; i++) { a[i]=1; } for(i=1; i<n; i++){ for(j=0; j<=m; j++) { if(a[j]){ //按照约束条件来取数 for(k=c[i][0]; k+j<=m && k<=c[i][1]; k++){ b[k+j] += a[j]; } } } for(j=0; j<=m; j++){ a[j]=b[j]; b[j]=0; } }
题意:有1,5,10,25,50, 5种硬币。给你一个价值总额,拆分实现价值总额
所用硬币总数不能超过100
a[i][j]代表j枚银币实现价值为i的方案数
a[0][0]=1; //题目说明0的拆分方法为1
for(i=1; i<6; i++) { for(j=0; j<=250; j++){ for(k=0; k*c[i]+j<=250; k++){ for(co=0; co+k<=100; co++) {//保证硬币总数符合要求 b[j+k*c[i]][co+k] += a[j][co]; } } } for(j=0; j<=250; j++){ for(co=0; co<=100; co++){ a[j][co]=b[j][co]; b[j][co]=0; } } }

浙公网安备 33010602011771号