题目链接:https://acm.sdtbu.edu.cn/vjudge/contest/view.action?cid=2482#problem/A
题意: 有无限多张1,2^2, 3^2, 4^2…… 17^2,共17种面值的货币,每次给定一个金额,问通过这17种货币有多少种换算的可能?
思路: 母函数来做,估计做这个题的都是第一次听到这个名词吧,其实并没有很神秘,就是有n个多项式相乘,n代表有多少种货币。n个多项式累乘结果内部第j个变量的指数代表金额,系数是可能。至于母函数如何构造等等推荐这篇文章我是传送门
代码:
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<algorithm>
#include<vector>
#include<cstring>
#include<queue>
#include<set>
#include<map>
using namespace std;
const int N = 310, INF = 0x3f3f3f3f;
typedef pair<int, int> PII;
typedef long long ll;
ll n;
ll a[N],b[N];
int main()
{
//结果的系数是可能数,指数是指定金额数值
while (cin >> n && n)
{
for(int i=0;i<=n;++i)//初始化第一个多项式
{
a[i] = 1;//第一个多项式系数全为1
b[i] = 0;
}
//共17种硬币对应17个多项式
for (int i = 2; i <= 17; ++i)
{
//"前i-1个多项式累乘的表达式里第j个变量
for (int j = 0; j <= n; ++j)
{
//第i个多项式,为什么是k+=i*i?因为第i个表达式里相邻变量的指数相差i*i
for (int k = 0; k + j <= n; k += i * i)
//j+k即为前i个多项式累乘的表达式中的某个变量; j同上,前i-1个多项式的值预存在数组a中
b[j + k] += a[j];
}
//将前i个多项式累乘的结果存到a中,b因为要在下次循环中存前i+1项多项式累乘的结果所以要赋0值
for (int j = 0; j <= n; j++)
{
a[j] = b[j];
b[j] = 0;
}
}
cout << a[n]<<endl;
}
return 0;
}