/**
* 刚开始做dp题,不习惯啊。看人代码还理解了老半天。。
* 动态规划 入门题
* 一直在想dp[i][j]是什么意思。。其实为了避免重复的选取,也就是分钱。
* 目标num,可以按时间阶段选取,比如第一次选取coins[0](也就是1) 那总数num就应该减一,即num-coins[0]
* 这样循环下令j从0-4,也就是5种硬币都要选取,这样就不会遗漏也不会重复了。
* 所以dp[i][j]的具体含义就是,对i值的钱分配,用第j种硬币以后的可能分配方法数
* dp的核心就是状态和状态转移方程。。
* 本题状态转移就是一开始的币值num 在经过5种选择之后会分别转移到 num-coins[i].
*/
#include <cstdio>
#include <cstring>
#include <cmath>
#include <stack>
#include <string>
#include <queue>
#include <map>
#include <algorithm>
#define INF 0x7fffffff
using namespace std;
int dp[7500][5], coins[5] = {1, 5, 10, 25, 50};
int dfs(int num, int t) {
if(dp[num][t] != -1)
return dp[num][t];
dp[num][t] = 0;
/* 不是从i=0开始,避免重复! */
for(int i = t; i < 5; i ++) {
if(num >= coins[i])
dp[num][t] += dfs(num - coins[i], i);
}
return dp[num][t];
}
int main()
{
int num;
/* 如果把这个初始化放while里会超时! 因为这样每次都初始化,就不能记录之前所计算的值了 */
memset(dp, -1, sizeof(dp));
for(int i = 0; i < 5; i++)
dp[0][i] = 1;
while(scanf("%d", &num) != EOF) {
printf("%d\n", dfs(num, 0));
}
return 0;
}