母函数简单应用小结

来源:互联网 发布:恶灵退散意思知乎 编辑:程序博客网 时间:2024/06/08 14:48

今天跟着伟峰大佬补基础,做到一题母函数的题。感觉贼刺激。
学习可以百度一下母函数有个博客讲的挺详细的里面还有模板。
然后拉了套kuangbin的母函数,感觉里面的题目大同小异。

A - Square Coins HDU - 1398
People in Silverland use square coins. Not only they have square shapes but also their values are square numbers. Coins with values of all square numbers up to 289 (=17^2), i.e., 1-credit coins, 4-credit coins, 9-credit coins, …, and 289-credit coins, are available in Silverland.
There are four combinations of coins to pay ten credits:

ten 1-credit coins,one 4-credit coin and six 1-credit coins,two 4-credit coins and two 1-credit coins, andone 9-credit coin and one 1-credit coin.Your mission is to count the number of ways to pay a given amount using coins of Silverland.

Input
The input consists of lines each containing an integer meaning an amount to be paid, followed by a line containing a zero. You may assume that all the amounts are positive and less than 300.
Output
For each of the given amount, one line containing a single integer representing the number of combinations of coins should be output. No other characters should appear in the output.
Sample Input

210300

Sample Output

1427

题意:让你用平方数取组成给的n有几种组成方法。
思路:典型的母函数让你求给定数字的组成个数。幂次为你能够组成的数字,对应的系数为组成该幂次的方案数。

#include<iostream>#include<algorithm>#include<vector>#include<queue>#include<vector>#include<cmath>#include<cstdio>#include<cstring>#include<string>#include<stack>#include<map>using namespace std;//thanks to pyf ...//thanks to qhl ...#define INF 0x3f3f3f3f#define CLR(x,y) memset(x,y,sizeof(x))#define mp(x,y) make_pair(x,y)typedef pair<int,int> PII;typedef long long ll;const int N = 1e5+5;int c1[N];int c2[N];int Max_N = 17;int Max_M = 310;void f(){    for(int i = 0; i <= Max_M;i++)        c1[i] = 1,c2[i] = 0;    for(int i = 2 ; i <=  Max_N;i++)    {        for(int j = 0; j <= Max_M; j++)        {            for(int k=0;k<=Max_M;k+=pow(i,2))            {                if(j+k <= Max_M);                    c2[j+k] += c1[j];            }        }        for(int j=0;j<=Max_M;j++)            c1[j] = c2[j],c2[j] = 0;    }}int main(){    int n;    f();    while(cin >> n && n)    {        cout << c1[n] << endl;    }}

B - Holding Bin-Laden Captive! HDU - 1085
We all know that Bin-Laden is a notorious terrorist, and he has disappeared for a long time. But recently, it is reported that he hides in Hang Zhou of China!
“Oh, God! How terrible! ”
Don’t be so afraid, guys. Although he hides in a cave of Hang Zhou, he dares not to go out. Laden is so bored recent years that he fling himself into some math problems, and he said that if anyone can solve his problem, he will give himself up!
Ha-ha! Obviously, Laden is too proud of his intelligence! But, what is his problem?
“Given some Chinese Coins (硬币) (three kinds– 1, 2, 5), and their number is num_1, num_2 and num_5 respectively, please output the minimum value that you cannot pay with given coins.”
You, super ACMer, should solve the problem easily, and don’t forget to take $25000000 from Bush!
Input
Input contains multiple test cases. Each test case contains 3 positive integers num_1, num_2 and num_5 (0<=num_i<=1000). A test case containing 0 0 0 terminates the input and this test case is not to be processed.
Output
Output the minimum positive value that one cannot pay with given coins, one line for one case.
Sample Input

1 1 30 0 0

Sample Output

4

题意:用给定张数的一块两块五块钱问你最小的不能组成的数是多少。
思路:那么对每个情况来说如果他的系数为0那么就说明没有组成他的方案就是无法组成。从1开始遍历找到第一个系数为0的情况

#include<iostream>#include<algorithm>#include<vector>#include<queue>#include<vector>#include<cmath>#include<cstdio>#include<cstring>#include<string>#include<stack>#include<map>using namespace std;//thanks to pyf ...//thanks to qhl ...#define INF 0x3f3f3f3f#define CLR(x,y) memset(x,y,sizeof(x))#define mp(x,y) make_pair(x,y)typedef pair<int,int> PII;typedef long long ll;const int N = 1e5+5;int v[3] = {1,2,5};int cnt[3];int c1[N];int c2[N];int main(){    while(cin >> cnt[0] >> cnt[1] >> cnt[2] && (cnt[0] || cnt[1] || cnt[2]))    {        CLR(c1,0);        CLR(c2,0);        int sum = 0;        for(int i=0;i<3;i++)            sum += cnt[i] * v[i];        for(int i = 0;i<=cnt[0]*v[0];i++)            c1[i] = 1, c2[i] = 0;        for(int i= 1;i<3;i++)        {            for(int j=0;j<=sum;j++)            {                for(int k = 0;k<=cnt[i]*v[i];k+=v[i])                {                    c2[j+k] += c1[j];                }            }            for(int j=0;j<=sum;j++)                c1[j] = c2[j] , c2[j] = 0;        }        int ans = 0;        for(ans = 0 ;ans <= sum ;ans ++)            if(c1[ans]==0)                break;        cout << ans << endl;    }}

C - Big Event in HDU HDU - 1171

 Nowadays, we all know that Computer College is the biggest department in HDU. But, maybe you don't know that Computer College had ever been split into Computer College and Software College in 2002.    The splitting is absolutely a big event in HDU! At the same time, it is a trouble thing too. All facilities must go halves. First, all facilities are assessed, and two facilities are thought to be same if they have the same value. It is assumed that there is N (0<N<1000) kinds of facilities (different value, different kinds).Input    Input contains multiple test cases. Each test case starts with a number N (0 < N <= 50 -- the total number of different facilities). The next N lines contain an integer V (0<V<=50 --value of facility) and an integer M (0<M<=100 --corresponding number of the facilities) each. You can assume that all V are different.    A test case starting with a negative integer terminates input and this test case is not to be processed.Output    For each case, print one line containing two integers A and B which denote the value of Computer College and Software College will get respectively. A and B should be as equal as possible. At the same time, you should guarantee that A is not less than B.Sample Input    2    10 1    20 1    3    10 1     20 2    30 1    -1Sample Output    20 10    40 40

&&&&这题最坑的是n<=-1&&&&

题意:给你一种物品的数量和价值,让你将它们尽量均分成两份,求每份的价值和。
思路:本来是一道背包的经典题,以总和的一半为背包容量,做一次多重背包就可以了。那么用母函数的思想同样去求1-m/2之间最小系数为0的幂次,那么就可以做了。坑点如上。。。

#include<iostream>#include<algorithm>#include<vector>#include<queue>#include<vector>#include<cmath>#include<cstdio>#include<cstring>#include<string>#include<stack>#include<map>using namespace std;//thanks to pyf ...//thanks to qhl ...#define INF 0x3f3f3f3f#define CLR(x,y) memset(x,y,sizeof(x))#define mp(x,y) make_pair(x,y)typedef pair<int,int> PII;typedef long long ll;const int N = 50*50*1000+100;int cnt[1005];int v[1005];int c1[N];int c2[N];int main(){    int n;    while(cin >> n)    {        if(n<=-1)            break;        int sum  = 0;        for(int i=0;i<n;i++)            cin >> v[i] >> cnt[i];        for(int i=0;i<n;i++)            sum += v[i]*cnt[i];        CLR(c1,0);        CLR(c2,0);//      for(int i=0;i<=cnt[0]*v[0];i+=v[0])//          c1[i] = 1,c2[i] = 0;        c1[0] = 1;        for(int i=0;i<n;i++)        {            for(int j=0;j<=sum/2;j++)            {                for(int k = 0 ;k<=cnt[i]*v[i];k+=v[i])                {                    if(j+k <= sum/2&&(c2[j+k]||c1[j]))                        c2[j+k] = 1;                }            }            for(int j=0;j<=sum/2;j++)                c1[j] = c2[j] ,c2[j] = 0;        }           int ans ;               for(ans=sum/2;ans>=0;ans--)            if(c1[ans])                break;        cout << sum-ans << " " << ans << endl;      }    return 0;}

D - Ignatius and the Princess III HDU - 1028
“Well, it seems the first problem is too easy. I will let you know how foolish you are later.” feng5166 says.

“The second problem is, given an positive integer N, we define an equation like this:
N=a1+a2+a3+…+am;
ai

0,1<=m<=N;
My question is how many different equations you can find for a given N.
For example, assume N is 4, we can find:
4 = 4;
4 = 3 + 1;
4 = 2 + 2;
4 = 2 + 1 + 1;
4 = 1 + 1 + 1 + 1;
so the result is 5 when N is 4. Note that “4 = 3 + 1” and “4 = 1 + 3” is the same in this problem. Now, you do it!”
Input
The input contains several test cases. Each test case contains a positive integer N(1<=N<=120) which is mentioned above. The input is terminated by the end of file.
Output
For each test case, you have to output a line contains an integer P which indicate the different equations you have found.
Sample Input

41020

Sample Output

542627

最后这题其实是跟着伟峰大佬做的这题。看到最后其实是最简单的,但是除了母函数的模型以外,还可以直接用记忆化搜索加上递归整数分割的思想。递归整数分割相当于有n个空盘子,把n个苹果可以空的放置到n个盘子里,盘子和苹果均相同。代码如下,两种方法都有。注释的是递归方法,没有注释的是母函数

#include<iostream>#include<algorithm>#include<vector>#include<queue>#include<vector>#include<cmath>#include<cstdio>#include<cstring>#include<string>#include<stack>#include<map>using namespace std;//thanks to pyf ...//thanks to qhl ...#define INF 0x3f3f3f3f#define CLR(x,y) memset(x,y,sizeof(x))#define mp(x,y) make_pair(x,y)typedef pair<int,int> PII;typedef long long ll;const int N = 1e5+5;////int dp[200][200];////int dfs(int n,int m) // he wei n chaishu//{//  if(dp[n][m])//      return dp[n][m];//  if(n==0||n==1||m==0||m==1)//      return dp[n][m] = 1;//  if(n < m)//      return dp[n][m] = dfs(n,n);//  else//      return dp[n][m] = (dfs(n,m-1)+dfs(n-m,m));//}////void f()//{//  CLR(dp,0);//  for(int i=1;i<=120;i++)//  {//      dfs(i,i);//  }//}//int main()//{//  int n;//  f();//  while(cin >> n)//  {//      cout << dp[n][n] << endl;//  }//}int c1[N];int c2[N];int main(){    int n;    while(cin >> n)    {        CLR(c1,0);        CLR(c2,0);        for(int i=0;i<=n;i++)            c1[i] = 1,c2[i] = 0;        for(int i=2;i<=n;i++)        {            for(int j=0;j<=n;j++)            {                for(int k = 0;k<=n;k+=i)                {                    c2[k+j] += c1[j];                   }               }               for(int j = 0;j<=n;j++)                c1[j] = c2[j] , c2[j] = 0;        }           cout << c1[n] << endl;    }}
原创粉丝点击