Square Coins (母函数)

本文介绍了一种使用母函数法解决硬币组合问题的算法实现。共有17种不同面值的硬币(从1^2到17^2),目标是计算组成任意给定数值的不同方式的数量。通过双重循环迭代更新状态数组来实现这一过程。

题目大意为:有1,4,9,16……..289(17^2)共17中不同的硬币,问有几种方法组成所给的数字。

母函数模板请看我的另一篇文章:
http://blog.youkuaiyun.com/rcy_zhu/article/details/75041050

在这题上,可以轻易得出价值数组v[i]为每种硬币的面值;
共17种,所以K=17;
因为每种硬币无限,所n2[i]数组省略;
每种硬币可取可不取,所以n1[i]为0;

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
using namespace std;
#define ll long long
#define inf 0xfffffff
#define N 302

int a[N],b[N];
int v[N];

int main()
{
    int n;
    for(int i=1;i<=17;i++)
        v[i]=i*i;
    while(cin>>n&&n)
    {
        memset(a,0,sizeof(a));
        a[0]=1;
        for(int i=1;i<=17;i++)
        {
            memset(b,0,sizeof(b));
            for(int j=0;j*v[i]<=n;j++)
            {
                for(int k=0;k+j*v[i]<=n;k++)
                    b[k+j*v[i]]+=a[k];
            }
            memcpy(a,b,sizeof(b));
        }
        cout<<a[n]<<endl;
    }
}
### C++ 中母函数的使用方法与实现 #### 普通型母函数的概念 普通型母函数是一种数学工具,主要用于解决多重集的组合问题。它通过构造一个多项式函数,使得多项式的各项系数和次数能够反映多重集的特性[^4]。 #### 母函数在 C++ 中的应用场景 母函数通常被用来处理涉及计数的问题,例如硬币面额组合、整数拆分等问题。这些问题可以通过构建对应的母函数并计算其展开形式来求解。以下是具体实现的方式: --- #### 母函数的代码实现 ##### 构造母函数的核心逻辑 母函数的本质是对多个多项式进行逐次相乘的操作。假设我们需要计算若干个多项式的乘积 \( H_1 \times H_2 \times H_3 \ldots \),可以按照如下方式进行模拟: 1. 初始化第一个多项式; 2. 将当前结果逐步与下一个多项式相乘; 3. 循环执行上述操作直至完成所有多项式的运算。 下面是一个具体的 C++ 实现示例,展示如何利用数组存储多项式的系数,并模拟多项式乘法的过程。 ```cpp #include <iostream> #include <vector> using namespace std; // 多项式乘法核心函数 void multiply(vector<int>& res, const vector<int>& poly) { int n = res.size(); int m = poly.size(); // 创建临时变量保存新的多项式结果 vector<int> temp(n + m - 1, 0); for (int i = 0; i < n; ++i) { for (int j = 0; j < m; ++j) { temp[i + j] += res[i] * poly[j]; } } // 更新结果向量 res = move(temp); } // 主程序入口 int main() { // 假设我们要计算几个多项式的乘积 vector<vector<int>> polynomials = { {1, 1}, {1, 1}, {1, 1} }; // 对应三个二项式 (1+x) // 初始结果为常数项 1 的多项式 vector<int> result = {1}; // 遍历每个多项式并与结果相乘 for (const auto& poly : polynomials) { multiply(result, poly); } // 输出最终结果 cout << "Resulting polynomial coefficients:" << endl; for (size_t i = 0; i < result.size(); ++i) { cout << "Coefficient of x^" << i << ": " << result[i] << endl; } return 0; } ``` --- #### 关键点解析 1. **多项式表示** 在代码中,多项式用一维数组 `vector<int>` 表示,其中索引代表幂次,值代表该幂次前的系数。例如 `[1, 2, 3]` 表示多项式 \( 1 + 2x + 3x^2 \)。 2. **多项式乘法** 使用嵌套循环遍历两个多项式的每一对项,将其乘积累加至目标位置。时间复杂度为 \( O(n \cdot m) \),其中 \( n \) 和 \( m \) 是两多项式的长度。 3. **动态更新结果** 结果多项式随着每次乘法不断扩展,因此需要创建一个新的临时数组来存储中间结果。 --- #### 应用实例 以下是一道经典的题目及其解决方案——给定若干种不同面额的硬币以及它们的数量限制,问总金额为 \( S \) 的方案总数是多少? ```cpp #include <iostream> #include <vector> using namespace std; void multiply(vector<long long>& res, const vector<long long>& poly) { int n = res.size(); int m = poly.size(); vector<long long> temp(n + m - 1, 0); for (int i = 0; i < n; ++i) { for (int j = 0; j < m && i + j < temp.size(); ++j) { temp[i + j] += res[i] * poly[j]; } } res = move(temp); } int main() { int numCoins; cin >> numCoins; vector<pair<int, int>> coins(numCoins); // 存储面额和数量限制 for (auto &coin : coins) { cin >> coin.first >> coin.second; // 输入面额和最大数量 } int targetSum; cin >> targetSum; // 初始化结果多项式 vector<long long> result(1, 1); for (const auto &[value, limit] : coins) { vector<long long> currentPoly(limit + 1, 0); for (int k = 0; k <= limit; ++k) { if (k * value > targetSum) break; currentPoly[k] = 1; } multiply(result, currentPoly); } // 找到目标金额对应的系数 if (targetSum >= result.size()) { cout << "No solution." << endl; } else { cout << "Number of ways to make sum " << targetSum << ": " << result[targetSum] << endl; } return 0; } ``` 此代码实现了基于母函数的方法,解决了硬币组合问题。 --- #### 总结 C++ 中母函数的实现主要依赖于多项式乘法的思想。通过对多项式进行逐层累乘,我们可以高效地解决问题中的组合情况。这种技术广泛应用于 ACM 竞赛以及其他算法领域。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值