HDU1398-Square Coins,HDU1028-Ignatius and the Princess III(母函数)

Square Coins

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 6083    Accepted Submission(s): 4105


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.

Output
For each of the given amount, one line containing a single integer representing the number of combinations of coins should be output. No other characters should appear in the output.

Sample Input
  
  
2 10 30 0

Sample Output
  
  
1 4 27
 
题目大意:
有一些硬币,奇特的是这些硬币的面值都是平方数,比如1,4,9,16,25。。。。289(17*17),现在给你一个数值,你用这些种硬币能够有多少种方法凑出这个钱数?每种面值的硬币可以用多次。
 
分析:典型的母函数的题目,具体什么叫做母函数,这里就不多说了,参见HDU的课件,讲的很好,这里只对这个母函数计算的模板进行讲解,自己刚开始看的时候好费劲啊!
 
代码:
 
#include<stdio.h>
#define lmax 300
int c1[lmax+1],c2[lmax+1];
//c1数组用于保存已经取得的结果,c2用于每增加一个括号的计算,计算过程中c1,c2都是用下标存储幂,数值存储系数
//比如c1[2]=3,则表示已经取得的x^2的项的系数是3 
int main(){	
	int n,i,j,k;
	while(scanf("%d",&n)&&n!=0){	
		for(i=0;i<=n;i++){	
			c1[i]=1;//刚开始结果只包含了一个括号,(1+x^1+x^2+...x^n)各个次幂的系数都是1 
			c2[i]=0;	
		}
		for(i=2;i<=17;i++){
            //i用于将第几个括号乘到结果中去,因为初始化的时候第一个括号已经计算过了,所以接着将第二个括号乘到结果里面去 
			for(j=0;j<=n;j++){
            //两个括号里的多项式相乘的时候,j用于取出第一个括号里面的第j项 
				for(k=0;k+j<=n;k+=i*i){
                    //k用于取出第二个多项式的第k项,这一项的幂0,4,8,12,16.....等,表示面值为4的硬币取0、1、2...n个 
					c2[j+k]+=c1[j];
					//两项相乘之后更新幂为j+k的项,因为第二个括号中x^k的系数为1,所以和前一个括号里c1[j]*x^j相乘之后,得到的新的x^(i+k的系数为c1[j]
                    //接着和之前得到的x^(i+j)项合并,系数相加,保存到c2[i+j]中去。 
				}
            }
			for(j=0;j<=n;j++){
				c1[j]=c2[j];//再将得到的多项式的值回写到c1里面,c2清零
				c2[j]=0;	
			}
		}
		printf("%d\n",c1[n]);
	}
	return 0;
}
/*
同样解法的还有整数拆分的问题,自己写出母函数,和上面类似,G(x)=(1+x+x^2+x^3...+x^n)*(1+x^2+x^4+x^6...)*(1+x^3+x^6...)....
代码:
*/
#include<stdio.h>
#define lmax 1000  
int c1[lmax+1],c2[lmax+1]; 
int main() {	
	int n,i,j,k; 	
	while(scanf("%d",&n)!=EOF) 	
	{
		for(i=0;i<=n;i++){
			c1[i]=1;	
			c2[i]=0;	
		}
		for(i=2;i<=n;i++){	
			for(j=0;j<=n;j++)		
				for(k=0;k+j<=n;k+=i){
					c2[j+k]+=c1[j];  
				}
				
			for(j=0;j<=n;j++){  
				c1[j]=c2[j];	
				c2[j]=0;  
			} 		
		} 		
		printf("%d\n",c1[n]);
	} 	
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值