zoukankan      html  css  js  c++  java
  • 母函数初学四大题

    关于什么是母函数以及母函数的模板什么的,大家可以去找杭电关于母函数的一个课件,还有一位大神的详解,附上网址:     http://www.cnblogs.com/freewater/archive/2012/09/11/2679734.html

    在此为入门四个题附上解题报告,仅供参考:

    现在以每种种类个数无限为例,给出模板::

     1 #include <iostream>
     2 using namespace std;
     3 // Author: Tanky Woo
     4 // www.wutianqi.com
     5 const int _max = 10001; 
     6 // c1是保存各项质量砝码可以组合的数目
     7 // c2是中间量,保存每一次的情况
     8 int c1[_max], c2[_max];   
     9 int main()
    10 {    //int n,i,j,k;
    11     int nNum;   // 
    12     int i, j, k;
    13 
    14     while(cin >> nNum)
    15     {
    16         for(i=0; i<=nNum; ++i)   // ---- ①
    17         {
    18             c1[i] = 1;
    19             c2[i] = 0;
    20         }
    21         for(i=2; i<=nNum; ++i)   // ----- ②
    22         {
    23 
    24             for(j=0; j<=nNum; ++j)   // ----- ③
    25                 for(k=0; k+j<=nNum; k+=i)  // ---- ④
    26                 {
    27                     c2[j+k] += c1[j];
    28                 }
    29                 for(j=0; j<=nNum; ++j)     // ---- ⑤
    30                 {
    31                     c1[j] = c2[j];
    32                     c2[j] = 0;
    33                 }
    34         }
    35         cout << c1[nNum] << endl;
    36     }
    37     return 0;
    38 }

    ①  、首先对c1初始化,由第一个表达式(1+x+x^2+..x^n)初始化,把质量从0到n的所有砝码都初始化为1.

    ②  、 i从2到n遍历,这里i就是指第i个表达式,上面给出的第二种母函数关系式里,每一个括号括起来的就是一个表达式。

    ③、j 从0到n遍历,这里j就是(前面i個表达式累乘的表达式)里第j个变量,(这里感谢一下seagg朋友给我指出的错误,大家可以看下留言处的讨论)。如(1+x)(1+x^2)(1+x^3),j先指示的是1和x的系数,i=2执行完之后变为

    (1+x+x^2+x^3)(1+x^3),这时候j应该指示的是合并后的第一个括号的四个变量的系数。

    ④ 、 k表示的是第j个指数,所以k每次增i(因为第i个表达式的增量是i)。

    ⑤  、把c2的值赋给c1,而把c2初始化为0,因为c2每次是从一个表达式中开始的。

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

        题目大意不用我说了吧?太简单了,理解了模板这题就A了

        

     1 #include <iostream>
     2 #include<stdio.h>
     3 using namespace std;
     4 const int _max = 300;
     5 int c1[_max], c2[_max];
     6 int main()
     7 {
     8     int n;
     9     int i, j, k;
    10     while(scanf("%d",&n)!=EOF)
    11     {
    12         for(i=0; i<=n; ++i)
    13         {
    14             c1[i] = 1;
    15             c2[i] = 0;
    16         }
    17         for(i=2; i<=n; ++i)
    18         {
    19 
    20             for(j=0; j<=n; ++j)
    21                 for(k=0; k+j<=n; k+=i)
    22                 {
    23                     c2[j+k] += c1[j];
    24                 }
    25                 for(j=0; j<=n; ++j)
    26                 {
    27                     c1[j] = c2[j];
    28                     c2[j] = 0;
    29                 }
    30         }
    31         printf("%d
    ",c1[n]);
    32     }
    33     return 0;
    34 }

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

    题目大意:

        硬币的面值分别为1,4,9,16.....17^2,输入n,问最多有几种组成方式。

        由题意我们可以写出母函数表达式:(1+x^1+x^2+x^3.....)*(1+x^4+x^8+x^12.....)*(1+x^9+x^18+......).....

        由该表达式,我们只需改动原模板的几个地方即可,具体看代码:

          

     1 #include <iostream>
     2 #include<stdio.h>
     3 #define maxn 301
     4 using namespace std;
     5 int c1[maxn],c2[maxn];
     6 int main()
     7 {
     8     int n,i,j,k;
     9     while(scanf("%d",&n)&& n!=0)
    10     {
    11         for (i=0; i<=n; ++i)
    12         {
    13             c1[i]=1;
    14             c2[i]=0;
    15         }
    16         for (i=2; i<18; ++i)//有17组表达式
    17         {
    18             for (j=0; j<=n; ++j)
    19                 for (k=0; k+j<=n; k+=i*i)//每次加i*i
    20                 {
    21                     c2[j+k]+=c1[j];
    22                 }
    23             for(j=0; j<=n; ++j)
    24             {
    25                 c1[j]=c2[j];
    26                 c2[j]=0;
    27             }
    28         }
    29         printf("%d
    ",c1[n]);
    30     }
    31     return 0;
    32 }

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

          这道题终于有了一些变化,仔细分析也不难,给你面值为1,2,5的硬币的个数,问最小的不能由这些硬币组成的价值。

          

     1 #include<stdio.h>
     2 #include<string.h>
     3 #define maxn 10001
     4 int c1[maxn],c2[maxn];
     5 int main()
     6 {
     7     int w[4]={0,1,2,5};//存面额
     8     int num[4];//存相应面额的个数
     9     int i,j,k;
    10     int sum,ksum;
    11     while(scanf("%d%d%d",&num[1],&num[2],&num[3])!=EOF)
    12     {
    13         if(num[1]==0&&num[2]==0&&num[3]==0)
    14             break;
    15         sum=num[1]+num[2]*2+num[3]*5;//最大能组成的面额数
    16         memset(c1,0,sizeof(c1));
    17         memset(c2,0,sizeof(c2));
    18         for(i=0; i<=w[1]*num[1]; i+=w[1])
    19             c1[i]=1;//初始化
    20         ksum=w[1]*num[1];
    21         for(i=2; i<=3; ++i)
    22         {
    23             for(j=0; j<=ksum; ++j)
    24                 for(k=0; k<=num[i]*w[i]; k+=w[i])//注意此处
    25                     c2[k+j]=c1[j];
    26             for(j=0; j<=ksum+w[i]*num[i]; ++j)
    27             {
    28                 c1[j]=c2[j];
    29                 c2[j]=0;
    30             }
    31             ksum+=w[i]*num[i];
    32         }
    33         for(i=0; i<=sum; i++)
    34             if(c1[i]==0)
    35             {
    36                 printf("%d
    ",i);
    37                 break;
    38             }
    39         if(i==sum+1)
    40             printf("%d
    ",sum+1);
    41     }
    42     return 0;
    43 }

    万变不离其宗,请大家结合代码好好分析。

      

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

         和第三题相似,最后要求输出的是分成两份的钱相等的情况,如果不相等,使差值尽可能小

     1 #include<stdio.h>
     2 #include<string.h>
     3 #define maxn 3000000
     4 int c1[maxn],c2[maxn],num[55],w[55];
     5 int main()
     6 {
     7     int n,i,j,k;
     8     int sum,ksum;
     9     while(scanf("%d",&n)!=EOF)
    10     {
    11         sum=0;
    12         if(n<0)
    13             break;
    14         memset(c1,0,sizeof(c1));
    15         memset(c2,0,sizeof(c2));
    16         for(i=1; i<=n; i++)
    17         {
    18             scanf("%d%d",&w[i],&num[i]);
    19             sum+=w[i]*num[i];
    20         }
    21         for(i=0; i<=w[1]*num[1]; i+=w[1])
    22             c1[i]=1;
    23         ksum=w[1]*num[1];
    24         for(i=2; i<=n; ++i)
    25         {
    26             for(j=0; j<=ksum; ++j)
    27                 for(k=0; k<=num[i]*w[i]; k+=w[i])
    28                     c2[k+j]=c1[j];
    29             for(j=0; j<=ksum+w[i]*num[i]; ++j)
    30             {
    31                 c1[j]=c2[j];
    32                 c2[j]=0;
    33             }
    34             ksum+=w[i]*num[i];
    35         }
    36         for(i=sum/2; i>=0; --i)
    37             if(c1[i]!= 0)
    38             {
    39                 printf("%d %d
    ", sum-i, i);
    40                 break;
    41             }
    42     }
    43     return 0;
    44 }

    四道题目解完了,是不是很简单呢?

        推荐做题:HDOJ:1709,1028、1709、1085、1171、1398、2069、2152。

    ————Anonymous.PJQ
  • 相关阅读:
    重新想象 Windows 8 Store Apps (15) 控件 UI: 字体继承, Style, ControlTemplate, SystemResource, VisualState, VisualStateManager
    重新想象 Windows 8 Store Apps (12) 控件之 GridView 特性: 拖动项, 项尺寸可变, 分组显示
    返璞归真 asp.net mvc (10) asp.net mvc 4.0 新特性之 Web API
    与众不同 windows phone (29) Communication(通信)之与 OData 服务通信
    与众不同 windows phone (33) Communication(通信)之源特定组播 SSM(Source Specific Multicast)
    与众不同 windows phone (27) Feature(特性)之搜索的可扩展性, 程序的生命周期和页面的生命周期, 页面导航, 系统状态栏
    与众不同 windows phone (30) Communication(通信)之基于 Socket TCP 开发一个多人聊天室
    返璞归真 asp.net mvc (12) asp.net mvc 4.0 新特性之移动特性
    重新想象 Windows 8 Store Apps (2) 控件之按钮控件: Button, HyperlinkButton, RepeatButton, ToggleButton, RadioButton, CheckBox, ToggleSwitch
    重新想象 Windows 8 Store Apps (10) 控件之 ScrollViewer 特性: Chaining, Rail, Inertia, Snap, Zoom
  • 原文地址:https://www.cnblogs.com/PJQOOO/p/3878577.html
Copyright © 2011-2022 走看看