题目链接: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;
	
}