Square Coins HDU-1398

题目链接:HDU-1398

题目描述 Problem Description 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, and
one 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.

思路

题意很明显了,就是告诉你一个数字,询问有多少种方式组成这个数;

我们这里运用母函数求解;

如果你不了解母函数,以下为推荐的两篇学习母函数的博客
母函数学习
母函数学习2

母函数在我的理解就是把组合问题的加法法则和幂级数的乘幂对应起来,这样就可以解决一些问题;

到最后,指数的大小就是(价值,质量等),系数就是方案数;

当然,他可以优化一下,就是记录每个式子当前的最高次幂和上一次的最高次幂;
可以节省一定的时间;

在本题中,我们用v数组保存每个数的价值,然后n1表示最小选择的数量,这里默认为0,n2表示当前数最多有多少种选择(即上限).c1保存的是多项式的乘积。初始化只有一项 (1) . 然后c2每次存储下一项与之前项的乘积;
最后c1[n]存储的就是生成价值n的方案数;

代码

#include 
using namespace std;

#define N 20
#define MAX 310

int c1[MAX], c2[MAX], v[N], n1[N], n2[N];

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n;
    for(int i = 0; i < 17; i++)
    {
        v[i] = (i + 1) * (i + 1);
    }
    while(cin >> n, n)
    {
        memset(c1, 0, sizeof(c1));
        c1[0] = 1;
        for(int i = 0; i < 17; i++)
        {
            memset(c2, 0, sizeof(c2));
            for(int j = n1[i]; j * v[i] <= n; j++)
            {
                for(int k = 0; k + j * v[i] <= n; k++)
                {
                    c2[k + j * v[i]] += c1[k];
                }
            }
            memcpy(c1, c2, sizeof(c2));
        }
        cout << c1[n] << endl;
    }
    return 0;
}

你可能感兴趣的:(杭电oj)