• 母函数


    母函数:

      自己也做不出非常好的总结。

      这个不错:  http://blog.csdn.net/vsooda/article/details/7975485;

      主要先学一下普通母函数吧。

      1、

         有1克、2克、3克、4克的砝码各一 枚,能称出哪几种重量?每种重量各有几种可能方案?

      考虑用母函数来接吻这个问题:

      我们假设x表示砝码,x的指数表示砝码的重量,这样:

        1个1克的砝码可以用函数1+x表示,

        1个2克的砝码可以用函数1+x2表示,

        1个3克的砝码可以用函数1+x3表示,

        1个4克的砝码可以用函数1+x4表示,

       上面这四个式子懂吗?

      我们拿1+x2来说,前面已经说过,x表示砝码,x的指数表示重量,即这里就是一个质量为2的砝码,那么前面的1表示什么?1代表重量为2的砝码数量为0个。(理解!)

      b*x^n 就为重n的物品有几种组成方式。

      2、 

        还有一个无限多物品的,

        

      模板: 

    //代码很简洁, 但不太好理解;
    #include <iostream>
    using namespace std;
    const int Maxn = 10001;
    int c1[Maxn], c2[Maxn];
    int main()
    {
        int nNum; int i, j, k;
        while(cin >> nNum)
        {
            for(int i = 0; i <= nNum; i++)  //  1    //初始化本身+1;*3=3*/; 3=1+1+1; 3=1+2;
            {
                c1[i] = 1;
                c2[i] = 0;
            }
            for(int i = 2; i <= nNum; i++)   // 2   我认为可以理解为把第几个多项式乘进去; 
            {
                for(int j = 0; j <= nNum; j++) // 3    //遍历前边几个多项式乘积和指数;
                    for(int k = 0; k+j <= nNum; k+=i)  // 4  待乘多项式中的项指数
                    {
                        c2[j+k] += c1[j];
                    }
                    for(j = 0; j <= nNum; j++)   // 5 、更新, c2清零; 
                    {
                        c1[j] = c2[j];
                        c2[j] = 0;
                    } 
            }
            cout << c1[nNum] << endl;
        }
        return 0;
    }

    1、

      hdoj 1028--Ignatius and the Princess III

           模板直接过;

    2、

      hdoj 1398--Square Coins

      所给元素不是连续的 而是i^2 (i = 1---->n) && i^2<=289;  需要改一下模板,  2、4中的i改为i*i;

    #include <cstdio>
    int c1[301], c2[301];
    int main()
    {
        int nNum;
        while(scanf("%d", &nNum) != EOF, nNum)
        {
            for(int i = 0; i <= nNum; i++)
            {
                c1[i] = 1;
                c2[i] = 0;
            }
            for(int i = 2; i*i <= nNum; i++)
            {
                for(int j = 0; j <= nNum; j++)
                    for(int k = 0; k+j <= nNum; k+=i*i)
                    {
                        c2[k+j]+=c1[j];
                    }
                for(int j = 0; j <= nNum; j++)
                {
                    c1[j] = c2[j];
                    c2[j] = 0;
                }
            }
            printf("%d
    ", c1[nNum]);
        }
        return 0;
    }

    3、

      hdoj 1085--Holding Bin-Laden Captive!

      磨人的本拉登。

      题解: http://www.wutianqi.com/?p=592

    #include <cstdio>
    int c1[8001], c2[8001];
    int num[4];
    int main()
    {
        int nNum;
        while(scanf("%d%d%d", &num[1], &num[2], &num[3]), num[1], num[2], num[3])
        {
            int Max=num[1]+num[2]*2+num[3]*5;
            for(int i = 0; i <= Max; i++)
            {
                c1[i] = 0;
                c2[i] = 0;
            }
    
            for(int i = 0; i <= num[1]; i++)
                c1[i] = 1;
            for(int i = 0; i <= num[1]; i++)
                for(int j = 0; j <= num[2]*2; j+=2)
                    c2[j+i] += c1[i];
            for(int i = 0; i <= num[2]*2+num[1]*1; ++i)
            {
                c1[i] = c2[i];
                c2[i] = 0;
            }
    
            for(int i = 0; i <= num[1]*1+num[2]*2; i++)
                for(int j = 0; j <= num[3]*5; j+=5)
                    c2[j+i] += c1[i];
            for(int i = 0; i <= num[2]*2+num[3]*5+num[1]*1; i++)
            {
                c1[i] = c2[i];
                c2[i] = 0;
            }
    
            int i;
            for(i = 0; i <= Max; i++)
                if(c1[i] == 0)
                {
                    printf("%d
    ", i);
                    break;
                }
            if(i==Max+1)
                printf("%d
    ", i);
        }
        return 0;
    }

    4、

      hdoj1171--Big Event in HDU

      n种物品 有n种不同价值和数目, 分成最接近的两份;

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    
    int c1[250001], c2[250001];
    int value[55];
    int amount[55];
    int main()
    {
        int nNum;
        while(scanf("%d", &nNum) && nNum > 0)
        {
            memset(value, 0, sizeof(value));
            memset(amount, 0, sizeof(amount));
    
            int sum = 0;
            for(int i = 1; i <= nNum; ++i)
            {
                scanf("%d %d", &value[i], &amount[i]);
                sum += value[i]*amount[i];
            }
            memset(c1, 0, sizeof(c1));  // == memset(c1, 0, sum*sizeof(c1[0]));
            memset(c2, 0, sizeof(c2));
            for(int i = 0; i <= value[1]*amount[1]; i+=value[1])
                c1[i] = 1;
            int len = value[1]*amount[1];
            for(int i = 2; i <= nNum; ++i)
            {
                for(int j = 0; j <= len; ++j)
                    for(int k = 0; k <= value[i]*amount[i]; k+=value[i])
                    {
                        c2[k+j] += c1[j];
                    }
                len += value[i]*amount[i];
                for(int j = 0; j <= len; ++j)
                {
                    c1[j] = c2[j];
                    c2[j] = 0;
                }
            }
            for(int i = sum/2; i >= 0; --i)
            {
                if(c1[i])
                {
                    printf("%d %d
    ", sum-i, i);
                    break;
                }
            }
        }
        return 0;
    }

      

      

      

  • 相关阅读:
    sed命令用法详解
    Linux date命令的用法
    安装oracle客户端连接工具
    nginx安装
    orabbix监控oracle数据库
    Oracle数据库修改用户密码
    oracle数据库重启操作
    centos6.5安装oracle11.2.0.1.0数据库
    教你几招解决电脑假死现象
    (java实现)杭电oj 2097 Sky数
  • 原文地址:https://www.cnblogs.com/soTired/p/5113473.html
Copyright © 2020-2023  润新知