★实验任务有一堆石头,共有 m 个,现在要你把他们分成小于等于 n 堆,一共有多少种不同的分法。
★数据输入输入第一行包括一个正整数 T(T<=10),接下来共有 T 组数据,每组数据只有一行,每行有两个正整数,m 和 n(m,n<=20)。
★数据输出每组数据输出一个数 sum,表示 sum 种不同的分法。
输入示例
1
7 3
输出示例
8
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define DEBUG
unsigned long GPC(int n,int max){
if(n==1||max==1)
return 1;
if(n<max)
return GPC(n,n);
if(n==max)
return 1+GPC(n,n-1);
else
return GPC(n-max,max)+GPC(n,max-1);
}
int main(){
int a,n,m;
unsigned long count;
scanf("%d",&a);
while(a--){
scanf("%d%d",&n,&m);
count=GPC(n,m);
printf("%d\n",count);
}
return 0;
}
使用递归:
(1)当n=1时,不论m的值为多少(m>0),只有一种划分,即{1,1,1,1········1};
(2)当m=1时,不论n的值为多少(n>0),只有一种划分,即{1};
(3)当m=n时,根据划分中是否包含m,可以分为两种情况:
(a)划分中包含m的情况,只有一个,即{m};
(b)划分中不包含m的情况,这时划分中最大的数字也一定比m小,即m的所有(m-1)划分;
因此,f(m,m) = 1 + f(m, m- 1)。
4)当m<n时,由于划分中不可能出现负数,因此就相当于f(m,m);
5)当m>n时,根据划分中是否包含n,可以分为两种情况:
(a)划分中包含n的情况,即{n,{x1,x2,x3,...,xi}},其中{x1,x2,x3,...,xi}的和为m-n,可能再次出现n,因此是(m-n)的n划分,因此这种划分个数为f(m-n,n);
(b)划分中不包含n的情况,则划分中所有值都比n小,即m的(n-1)划分,个数为f(m, n - 1);
因此,f(m,n) = f(m - n,n) + f(m, n - 1)。
n综合以上各种情况,可以看出,上面的结论具有递归定义的特征,其中(1)和(2)属于回归条件,(3)和(4)属于特殊情况,而情况(5)为通用情况,属于递归的方法,其本质主要是通过减少n或m以达到回归条件,从而解决问题。
n其递归表达式如下所示: