hdu 1028 Ignatius and the Princess III 母函数模板题

http://acm.hdu.edu.cn/showproblem.php?pid=1028

题意:

整数的拆分。

母函数学习http://www.wutianqi.com/?p=596

母函数题目_#include母函数题目_大括号_02View Code
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <string>

#define CL(a,num) memset((a),(num),sizeof(a))
#define iabs(x)  ((x) > 0 ? (x) : -(x))
#define Min(a , b) ((a) < (b) ? (a) : (b))
#define Max(a , b) ((a) > (b) ? (a) : (b))

#define ll __int64
#define inf 0x7f7f7f7f
#define MOD 100000007
#define lc l,m,rt<<1
#define rc m + 1,r,rt<<1|1
#define pi acos(-1.0)
#define test puts("<------------------->")
#define maxn 100007
#define M 100007
#define N 127
using namespace std;
//freopen("din.txt","r",stdin);

int c1[N],c2[N];

void init(int n){
    int i,j,k;
    for (i = 0; i <= n; ++i){
        c1[i] = 1;//乘完后的系数
        c2[i] = 0;//乘的过程中的系数
    }

    for (i = 2; i <= n; ++i){
        //总共有n个括号,从第2个起每一个括号都要和前面那一个括号相乘
    //所以可以忽略第一个括号 
        for (j = 0; j <= n; ++j){//j代表最前面这个大括号的项数 
            for (k = 0; k + j <= n; k += i){//在大括号后面,x都是以i方递增的 
                c2[k + j] += c1[j];//这里就是大括号后面的括号与前面相乘的计算 
            }
        }
        for (j = 0; j <= n; ++j){
            c1[j] = c2[j];
            c2[j] = 0;
        }
    }
}
int main(){
    int n;
    init(120);
    while (~scanf("%d",&n)){
        printf("%d\n",c1[n]);
    }
    return 0;
}

 

hdu 1398 Square Coins

http://acm.hdu.edu.cn/showproblem.php?pid=1398

题意:

整数拆分的题目,只不过后边的括号里面的差值变成了i^2吧了。。

母函数题目_#include母函数题目_大括号_02View Code
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <string>

#define CL(a,num) memset((a),(num),sizeof(a))
#define iabs(x)  ((x) > 0 ? (x) : -(x))
#define Min(a , b) ((a) < (b) ? (a) : (b))
#define Max(a , b) ((a) > (b) ? (a) : (b))

#define ll __int64
#define inf 0x7f7f7f7f
#define MOD 100000007
#define lc l,m,rt<<1
#define rc m + 1,r,rt<<1|1
#define pi acos(-1.0)
#define test puts("<------------------->")
#define maxn 100007
#define M 100007
#define N 327
using namespace std;
//freopen("din.txt","r",stdin);

int c1[N],c2[N];
int pow2[320];

void init(int n){

    int i,j,k;
    for (i = 1; i <= 300; ++i){
        pow2[i] = i*i;
    }
    for (i = 0; i <= n; ++i){
        c1[i] = 1;
        c2[i] = 0;
    }

    for (i = 2; i <= n; ++i){
        for (j = 0; j <= n; ++j){
            for (k = 0; k + j <= n; k += pow2[i]){
                c2[k + j] += c1[j];
            }
        }
        for (j = 0; j <= n; ++j){
            c1[j] = c2[j];
            c2[j] = 0;
        }
    }
}
int main(){
    int n;
    init(300);
    while (~scanf("%d",&n)){
        if (!n) break;
        printf("%d\n",c1[n]);
    }
    return 0;
}

 

hdu 1085 Holding Bin-Laden Captive!

http://acm.hdu.edu.cn/showproblem.php?pid=1085

题意:

给出三种硬币,价值分别为1,2,5并给出他们的数量num1,num2,num5问他们不能够组合出来的的最小价值;

思路:

前边我们介绍的都是要么是每种数量为1个或者无限个,而这里给出了确定的数量。而且询问的是不能组合出来额最小值。所以有点绕,但思路还是没有改变。

我们只要在进行乘法运算时动态的增加括号里的项数即可。最后从小到大枚举一下就好。。

母函数题目_#include母函数题目_大括号_02View Code
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <string>

#define CL(a,num) memset((a),(num),sizeof(a))
#define iabs(x)  ((x) > 0 ? (x) : -(x))
#define Min(a , b) ((a) < (b) ? (a) : (b))
#define Max(a , b) ((a) > (b) ? (a) : (b))

#define ll __int64
#define inf 0x7f7f7f7f
#define MOD 100000007
#define lc l,m,rt<<1
#define rc m + 1,r,rt<<1|1
#define pi acos(-1.0)
#define test puts("<------------------->")
#define maxn 100007
#define M 100007
#define N 8007
using namespace std;
//freopen("din.txt","r",stdin);

int c1[N],c2[N];

int main(){
    int i,j,k;
    int num1,num2,num5;
    while (~scanf("%d%d%d",&num1,&num2,&num5)){
        if (!num1 && !num2 && !num5) break;
        int MAX = num1 + num2*2 + num5*5;//本身所能表示的最大数
        for (i = 0; i <= MAX; ++i){
            c1[i] = 0;
            c2[i] = 0;
        }
        for (i = 0; i <= num1; ++i) c1[i] = 1;//初始化第一个括号里的项
        //成第二个括号里的项
        for (j = 0; j <= num1; ++j){
            for (k = 0; k <= num2*2; k += 2){
                c2[k + j] += c1[j];
            }
        }
        for (j = 0; j <= num1 + num2*2; ++j){//动态的添加了
            c1[j] = c2[j];
            c2[j] = 0;
        }
        for (j = 0; j <= num1 + num2*2; ++j){
            for (k = 0; k <= num5*5; k += 5){
                c2[k + j] += c1[j];
            }
        }
        for (j = 0; j <= MAX; ++j){
            c1[j] = c2[j];
            c2[j] = 0;
        }
        for (i = 1; i <= MAX; ++i){
            if (!c1[i]) break;
        }
        printf("%d\n",i);
    }
    return 0;
}

 hdu Big Event in HDU

http://acm.hdu.edu.cn/showproblem.php?pid=1171

题意:

给出N中不同的设备,分别给出他们的价值以及数量,将这些设备分为两组,尽量使这两组的价值相等。输出各自的价值,若不相等大的在前边;

思路:

和上边一样。。。不多讲;

母函数题目_#include母函数题目_大括号_02View Code
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <string>

#define CL(a,num) memset((a),(num),sizeof(a))
#define iabs(x)  ((x) > 0 ? (x) : -(x))
#define Min(a , b) ((a) < (b) ? (a) : (b))
#define Max(a , b) ((a) > (b) ? (a) : (b))

#define ll __int64
#define inf 0x7f7f7f7f
#define MOD 100000007
#define lc l,m,rt<<1
#define rc m + 1,r,rt<<1|1
#define pi acos(-1.0)
#define test puts("<------------------->")
#define maxn 100007
#define M 100007
#define N 250007
using namespace std;
//freopen("din.txt","r",stdin);

int c1[N],c2[N];

int num[55],val[55];

int main(){
   // freopen("din.txt","r",stdin);
    int n,i,j,k;
    while (~scanf("%d",&n)){
        if (n < 0) break;
        int MAX = 0;
        for (i = 0; i < n; ++i){
            scanf("%d%d",&val[i],&num[i]);
            MAX += (val[i]*num[i]);
        }
        for (i = 0; i <= MAX; ++i){
            c1[i] = c2[i] = 0;
        }
        int len = val[0]*num[0];
        for (i = 0; i <= len; i += val[0]){
            c1[i] = 1;
        }
        for (i = 1; i < n; ++i){
            for (j = 0; j <= len; ++j){
                for (k = 0; k <= val[i]*num[i]; k += val[i]){
                    c2[k + j] += c1[j];
                }
            }
            len += val[i]*num[i];
            for (j = 0; j <= len; ++j){
                c1[j] = c2[j];
                c2[j] = 0;
            }
        }
        int ave = MAX/2;
        for (i = ave; i >= 0; --i){
            if (c1[i]) break;
        }
        int A = i;
        int B = MAX - A;
        printf("%d %d\n",max(A,B),min(A,B));
    }
    return 0;
}