H - Holding Bin-Laden Captive! HDU - 1085(母函数-笔记)

 H - 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 3
0 0 0

Sample Output

4

第一次学习母函数,这里整理一下思路。

题意:给定指定数量的面额为1、2、5的硬币,问不能组成的最小面额。

思路:这道题是模拟多项式乘法的计算,用指数映射对应的硬币值,最后化简出来的多项式存在的系数代表对应面额的硬币存在。

(1+x+x^2+x^3+.........x^num[0])∗(1+x^2+x^4+x^6+.........x^num[1])∗(1+x^5+x^10+x^15+............x^num[2])

for循环计算i时,是把已化简的多项式与第i+1个括号的值进行乘法模拟计算

{

    for  循环 j 时,j值向已存在的系数的项

             {

                      for 循环 k时, k指向第i+1个括号里的每个项

                                  循环体

              }

}

数组a和t的下标都是指向系数的值,即面额值(数组值对应于该面额的方案数,这道题不用求方案数,也可以直接把t[j+k*val[i]]的值置为1表示存在该该面额的值。)

AC代码:

#include<cstdio>
#include<stack>
#include<set>
#include<vector>
#include<queue>
#include<algorithm>
#include<cstring>
#include<string>
#include<map>
#include<iostream>
#include<cmath>
using namespace std;
#define inf 0x3f3f3f3f
typedef long long ll;
const int N=10000+5;
const int MOD = 1e5+ 7;
int val[3]= {1,2,5}; //硬币值
int a[N],t[N],num[3];
int main()
{
    while(scanf("%d%d%d",&num[0],&num[1],&num[2])!=EOF)
    {
        if(num[0]==0&&num[1]==0&&num[2]==0)
            break;
        memset(a,0,sizeof(a));          //用来保存每种面额可以组成的方案
        memset(t,0,sizeof(t));
        int maxl=0;
        for(int i=0; i<3; i++)
            maxl+=val[i]*num[i];        //maxl为最大可能的面额值
        for(int i=0; i<=num[0]; i++)
            a[i]=1;              //等同a[i*val[0]]=1;
        for(int i=1; i<3; i++)
        {
            for(int j=0; j<=maxl; j++)  
            {
                if(a[j])   
                {
                    for(int k=0; k<=num[i]; k++)   //遍历val[i]硬币的取不同数量时的情况
                    {
                            //在面额为j存在的情况下,选择k个硬币值为val的硬币加入总面额
                            t[j+k*val[i]]+=a[j];   //t[j+k*val[i]]=1
                    }
                }
            }
          //模拟乘法,计算得到的多项式结果保留到数组a中
            memcpy(a,t,sizeof(a)); 
           //数组t作为中间变量,动手计算几项对理解有很好的帮助
            memset(t,0,sizeof(t));
        }
        for(int i=1; i<=maxl+1; i++)  
 //i<=maxl结果wrong,因为有可能全部maxl内的面额都可以组成
        {
            if(!a[i])
            {
                printf("%d\n",i);
                break;
            }
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/clz16251102113/article/details/81207958
今日推荐