- 题意:有1->17的平方数价值的金币,问用这些金币组成1->300内任意价值,有多少种组合方法。
- 思路:我们从小到大依次用这些平方数来组成1->300的价值
1:dp[ i ]=1;
4:dp[ 4 ]+=dp[ 4-4 ]=2; dp[ 5 ]+=dp[ 5-4 ]=2; dp[ 9 ]+=dp[ 9-4 ]=3;
9:dp[ 9 ]+=dp[ 9-9 ]=4; - 所有的数都能被1组成,这毫无疑问
- 举dp[ 8 ]=dp[ 8-4 ]+1=dp[ 4 ]+1(这里的1是完全由1组成8的情况)为例,8我们来想的话,有2x4,1x4,8x1,三种情况(不够的用1来补)。
- 8x1是跑1,每个dp[ i ]都变成了1(也就是0个4的情况)。
- 之后跑4,4=1x4=4x1(包含了0个4和1个4的情况),dp[ 8 ]+=dp[ 8-4 ]=dp[ 4 ],也就是包含了1个4,和2个4的情况。(也就是:8-4是一个4了,然后dp[ 4 ]有0个4和1个4的情况,于是dp[ 8 ]就包含了1个4,2个4的情况)
- 再来说说14,有14x1,1x4,2x4,3x4,1x9,4+9(不够的用1来补)六种情况。
- 跑到1,就是全是1的情况。
- 跑到4,dp[ 14 ]+=dp[ 14-4 ],dp[ 10 ]包含了2个4,1个4,0个4(没有包含1个9的情况是因为还没跑9),所以可以构成dp[ 14 ]现在有3个4,2个4,1个4。
- 跑到9的时候,dp[ 14 ]+=dp[ 14-9 ],这里的dp[ 5 ]是有了0个4,1个4两种情况,这两种和9来组合,就是1个9,4和9组合这两种
【自己手动模拟一遍其实很简单】
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cmath>
#include <cstring>
#include <string>
#include <vector>
#include <set>
#include <stack>
#include <list>
#include <map>
#define P(x) x>0?x:0
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
typedef vector<int>:: iterator VITer;
const int maxn=305;
int coin[18];
void ConstInt()
{
for(int i=0;i<=17;i++)
coin[i]=i*i;
}
int N;
int dp[maxn];
void init()
{
memset(dp,0, sizeof(dp));
dp[0]=1;
}
void solve()
{
init();
for(int i=1;i<=17;i++)
for(int j=coin[i];j<=300;j++)
dp[j]+=dp[j-coin[i]];
}
int main()
{
ConstInt();
solve();
while(~scanf("%d",&N) && N)
printf("%d\n",dp[N]);
return 0;
}