Staircases

Staircases

Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 32768/16384K (Java/Other)
Total Submission(s) : 8   Accepted Submission(s) : 5
Problem Description
One curious child has a set of   N  little bricks (5 ≤   N  ≤ 500). From these bricks he builds different staircases. Staircase consists of steps of different sizes in a strictly descending order. It is not allowed for staircase to have steps equal sizes. Every staircase consists of at least two steps and each step contains at least one brick. Picture gives examples of staircase for   N=11 and   N=5:
Problem illustration
Your task is to write a program that reads the number   N  and writes the only number   Q  amount of different staircases that can be built from exactly   N  bricks.
 

Input
Number   N
 

Output
Number   Q
 

Sample Input
  
  
inputoutput
212
995645335
 
 
 
 
 

题意

这道题目要求计算给定数目的砖块可以组成多少种不同的楼梯。楼梯由不同高度的阶梯组成,不允许有两个阶梯有相同的高度。每个楼梯至少包含两个阶梯,每个阶梯至少包含一个砖块。

数学背景

这道题目涉及到数的分划,属于组合数学数论的研究领域。

数 n 的分划(partition)是将 n 表示成任意多个正整数之和的形式。例如,数 5 的分划如下:

  1. 5
  2. 4 + 1
  3. 3 + 2
  4. 3 + 1 + 1
  5. 2 + 2 + 1
  6. 2 + 1 + 1 + 1
  7. 1 + 1 + 1 + 1 + 1

用 p(n) 来记 n 的分划的个数,这样就有 p(5) = 7。

为了求解 p(n),我们引入一个中间函数 p(k, n),表示数 n 的最小被加数不小于 k 的分划的个数。对于给定的 k 值,p(k, n) 正好分为以下两类:

  1. 最小被加数等于 k
  2. 最小被加数大于 k

满足第一个条件的分划的个数是 p(kn − k)。 这是因为,让我们想象数 n − k 的最小被加数不小于 k 的分划,然后将 "+ k" 附加每一个分划后面,就得到数 n 的最小被加数等于 k 的分划。以 n = 5, k = 1 为例,数 4 的最小被加数不小于 1 的分划是 43 + 12 + 22 + 1 + 1 和1 + 1 + 1 + 1,即 p(kn − k) = p(1, 4) = 5。然后,将 "+ 1" 附加在这 5 个分划后面,就得到数 5 的最小被加数等于 1 的分划:4 + 13 + 1 + 12 + 2 + 12 + 1 + 1 + 1 和 1 + 1 + 1 + 1 + 1

满足第二个条件的分划的个数是 p(k + 1, n) 。以 n = 5, k = 1 为例,数 5 的最小被加数大于 1 的分划是 5 和 3 + 2,即 p(k + 1, n) =p(2, 5) = 2。

也就是说,p(1, 5) = p(2, 5) + p(1, 4)。因此:

  • p(kn) = 0  如果 k > n
  • p(kn) = 1  如果 k = n
  • p(kn) = p(k+1, n) + p(kn-k)  其它情况

这样,就可以递归地求解 p(k, n),其部分值见下表:

 k
12345678910
n11000000000
22100000000
33110000000
45211000000
57211100000
611421110000
715421111000
822732111100
930842111110
10421253211111

最后,p(n) = p(1, n)

 


现在,让我们的来考虑 将 n 分成不相等的正整数之和的分划。例如,数 8 的分划如下:

  1. 8
  2. 7 + 1
  3. 6 + 2
  4. 5 + 3
  5. 5 + 2 + 1
  6. 4 + 3 + 1

用 q(n) 来记 n 的分划的个数,这样就有 q(8) = 6。

为了求解 q(n),我们引入一个中间函数 q(k, n),表示数 n 的最小被加数不小于 k 的分划的个数。对于给定的 k 值,q(k, n) 正好分为以下两类:

  1. 最小被加数等于 k
  2. 最小被加数大于 k

满足第一个条件的分划的个数是 q(k + 1, n − k)。 这是因为,让我们想象数 n − k 的最小被加数大于 k 的分划,然后将 "+ k" 附加每一个分划后面,就得到数 n 的最小被加数等于 k 的分划。以 n = 8, k = 1 为例,数 7 的最小被加数大于 1 的分划是 75 + 2 和 4 + 3,即 q(k + 1,n − k) = q(2, 7) = 3。然后,将 "+ 1" 附加在这 3 个分划后面,就得到数 8 的最小被加数等于 1 的分划:7 + 15 + 2 + 1 和 4 + 3 + 1

满足第二个条件的分划的个数是 q(k + 1, n) 。以 n = 8, k = 1 为例,数 8 的最小被加数大于 1 的分划是 86 + 2 和 5 + 3,即 q(k + 1,n) = q(2, 8) = 3。

也就是说,q(1, 8) = q(2, 8) + q(2, 7)。因此:

  • q(kn) = 0  如果 k > n
  • q(kn) = 1  如果 k = n
  • q(kn) = q(k+1, n) + q(k + 1, n-k)  其它情况

这样,就可以递归地求解 q(k, n),其部分值见下表:

 k
12345678910
n11000000000
21100000000
32110000000
42111000000
53211100000
64211110000
75321111000
86321111100
98532111110
1010532111111

最后,q(n) = q(1, n)

解题思路

用 n 块砖块可以组成的楼梯的个数,就是将 n 分成不相等的正整数之和的分划的个数 q(n) 减一,因为每个楼梯至少包含两个阶梯。

 

 

妈蛋坑逼数学题。。。

代码如下

#include<stdio.h>
double f[501][501];
int main(){
  long n,q,i,j;
  for (i=1;i<=500;++i)
   for (j=1;j<=500;++j){
    if (i==j) f[i][j]=1;
    else f[i][j]=0;
   }
  for(i=1;i<=500;++i)
   for(j=i-1;j>=1;--j)
    f[i][j]=f[i][j+1]+f[i-j][j+1];
  while (scanf("%d",&n)!=EOF && n!=0)
   printf("%.0lf\n",f[n][1]-1);
}


 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值