HDU - 1398 Square Coins (母函数)

版权声明:。。。 https://blog.csdn.net/dsaghjkye/article/details/79965837

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. 
InputThe 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. 
OutputFor 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个n,你有 1  4  9   16  25 ..... i^2 等元素,每个有无限个,现在问你你有几种方案,由任意个元素组成n

比如 

10    4种方案

1+9

1+1+....+1(10个)

4+1+.....+1(6个)

4+4+1+1

 解:c1[i]=j代表的是组成i的方案有j种,c2的意义和c1相同,不过c2是再引入1个新的元素后,方案的变化,然后我们把c2的值赋给c1,c2重新归零

比如 10

我们首先明白可以组成他的元素为  1,4,9,因为每个元素有无限个,不过我们得知道c1[0]=1,因为1个都不选也是一种状态

我们先拿出 元素k= 1  ,显然 for( i ,0 , 10)   c1[i] =1   唯一的方案就是 i 个1

然后拿出 元素 k=4   从 for(i,0,10),每个i 都可以 一直加k 直到值大于 10为止

0 :   c2[0]+=c1[0]     c2[4]+=c1[0]     c2[8]+=c1[0]

1:    c2[1]+=c1[1]    c2[5]+=c1[1]    c2[9]+=c1[1]

2 :    c2[2]+=c1[2]   c2[6]+=c1[2]  c2[10]+=c1[2]

............

然后我们把c2的值赋给c1,清空c2

拿出 元素  k=9   for(i,0,10) 每个i 都可以 一直加k 直到值大于 10为止

0:c2[0]+=c1[0]   c2[9]+=c1[0]  

............

#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<iostream>
#include<math.h>
#include<queue>
#include<map>
#include<vector>
#include<set>
using namespace std;
#define inf 0x3f3f3f3f
#define ll long long
int c1[330],c2[330];
int main()
{
    int n;
    while(~scanf("%d",&n)&&n)
    {
        for(int i=0;i<=n;i++)//元素 1 的情况
        {
            c1[i]=1;
            c2[i]=0;
        }
        for(int i=2;i*i<=n;i++)  //枚举小于等于n的元素
        {
            for(int j=0;j<=n;j++)//范围,因为最大只要到n即可
            {
                for(int k=0;k<=n;k+=i*i)//看最多能加几个当前元素
                {
                    c2[j+k]+=c1[j];  
                }
            }
            for(int j=0;j<=n;j++)//更新c1,c2
            {
                c1[j]=c2[j];
                c2[j]=0;
            }
        }
        printf("%d\n",c1[n]);
    }
}





阅读更多

没有更多推荐了,返回首页