【题目】如果正整数构成的集合X满足以下条件,我们称它为n-k特殊集:
1、集合X中的每个元素x均不超过n,即1<=x<=n.
2、集合X中所有的元素之和大于k.
3、集合X中不包含任意一对相邻的自然数.
给出n,k,求n-k特殊集合有多少个。1<=n<=100 ,0<=k<=400.
样例输入:6 3
样例输出:17
样例输入:14 55
样例输出:1
样例输入:40 1000
样例输出:367185615
【分析】设n-k特殊集的个数为f(n,k),我们要想办法来建立它的递推式。由于几何中的元素不能重复,元素n要么要集合中恰好出现一次,要么不出现,二者不重复、不遗漏地把n-k特殊集分成两部分:
1、n不出现。则f(n,k) = f(n-1,k).
2、n出现一次。则f(n,k) = f(n-2,k-n).
所以递推表达式为:f(n,k) = f(n-1,k) + f(n-2,k-n).
边界条件是什么呢?(这儿我也有点不懂)
当n<=0,k>=0时,f(0,k) = 0.
当n<=0,k<0时,f(0,k) = 1.
由上式可看出:k<0是,f(n,k)与k无关,用 -1 来代表所有的负数,这样可得到下式:
f(n,k) = 0(n = 0,-1,k>=0)
f(n,-1) = 1(n = 0,-1)
为了符合平时的书写习惯 ,我们用宏来处理负数的数组下标。
代码如下:
#include <iostream>
#include <cstdio>
using namespace std;
#define F(i,j) (f[(i)+1][(j)+1]) //宏处理
long long f[200][500];
int main()
{
int i,j,k,n;
while(cin>>n>>k){
for(j = -1; j <= k; j++)
F(-1,j) = F(0,j) = 0;
F(-1,-1) = F(0,-1) = 1;
for(i = 1; i <= n; i++)
for(j = -1; j <=k; j++){
F(i,j) = F(i-1,j);
if(j-i < 0)
F(i,j) += F(i-2,-1);
else
F(i ,j) += F(i-2,j-i);
}
cout<<F(n,k)<<endl;
}
return 0;
}