题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1284
Problem Description
在一个国家仅有1分,2分,3分硬币,将钱N兑换成硬币有很多种兑法。请你编程序计算出共有多少种兑法。
Input
每行只有一个正整数N,N小于32768。
Output
对应每个输入,输出兑换方法数。
Sample Input
293412553
Sample Output
71883113137761
题意.......中文题很清楚:
母函数求排列组合,核心思想:用数组代替多项式进行多项式相乘,其中数组下标代表次幂,数组下表对应的元素代表次数对应的系数。
代码如下:
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<string>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
#define da 100000
#define xiao -10000000
#define clean(a,b) memset(a,b,sizeof(a))
#define max 35000
int c1[100000],c2[100000]; //两个数组,相互乘;
int main()
{
int n;
int i,j,k;
for(i=0;i<=max;++i)
c1[i]=1; //初始化第一个数组的值为一,代表第一个的系数全为一;
for(i=2;i<=3;++i) //分为两个,二次幂和三次幂
{
for(j=0;j<=max;++j) //第一个的每个元素的系数i次循环
{
for(k=0;k<=max-j;k=k+i) //k+j<==max就行了,不用太多,每次
c2[k+j]=c2[j+k]+c1[j]; //相乘后次幂相加(对应的下标),与原来的次幂的系数相加;
}
for(j=0;j<=max;++j) //将第二个数组的值赋给第一个数组
c1[j]=c2[j];
clean(c2,0); //清空第二个数组的元素(系数为0),因为我们在这里时加法代替乘法,因此n*1=n+0(1+1=1+0)所以初始化为0就保证没有加上多余的数了;
}
while(~scanf("%d",&n)) //对于每次输入的整数;
printf("%d\n",c1[n]); //输出其的组合数目;
}
学了dp来挖一波坟:
记录每一个钱币的兑换方案,然后后面的加上前面的合成新的钱币的兑换方案:
#include<stdio.h>
#include<string.h>
#include<math.h>
//#include<map>
#include<set>
#include<deque>
#include<queue>
#include<stack>
#include<string>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
#define da 0x3f3f3f3f
#define xiao -0x3f3f3f3f
#define clean(a,b) memset(a,b,sizeof(a))// 雷打不动的头文件
ll dp[35000];
int n;
int main()
{
int i,j;
int shuzu[3]={1,2,3};
clean(dp,0);
dp[0]=1;
for(i=0;i<3;++i)
{
for(j=1;j<35000;++j)
dp[j]=dp[j]+dp[j-shuzu[i]];
}
while(cin>>n)
cout<<dp[n]<<endl;
}