现在的位置: 首页 > 综合 > 正文

N-K集合(dp)

2017年11月16日 ⁄ 综合 ⁄ 共 967字 ⁄ 字号 评论关闭

如有错误,请留言提醒,不要坑到小朋友

Description

我们说一个由自然数构成的集合X是n-k特殊集合,则它满足 
1 对于集合X中的每个元素x,有1<=x<=n, 
2 集合X中所有元素的和大于k, 
3 集合X中不包含任意一对相邻的自然数。 

任务 
● 读入两个自然数n和k, 
● 计算n-k特殊集合的个数, 

Input

第一行是两个自然数n和k,中间由一个空格隔开。 
1<=n<=100,0<=k<=400。 

Output

只有一个非负整数,代表了n-k集合的个数。 

Sample Input

5 6



Sample Output

3
用f[i][j]代表前i个数可以组成和小于等于j有多少个n-k集合
那么转移f[i][j]=f[i-2][j-i]+f[i-1][j];
最后答案就是f[n][k..(n+1)*n/2];
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<climits>
#define min(a,b) ((a)>(b)?(b):(a))
#define max(a,b) ((a)>(b)?(a):(b))
using namespace std;
long long f[302][10502],tot;
long long  n,k;
int main(){
//	freopen("a.in","r",stdin);
//	freopen("a.out","w",stdout);
	scanf("%I64d%I64d",&n,&k);
	tot=(long long)(1+n)*n/2;
	f[0][0]=1;f[1][1]=1;
	for(int i=1;i<=n;i++)
		for(int j=0;j<=tot;j++){
			f[i][j]+=f[i-1][j];
			if(i>=2&&j-i>=0)
			f[i][j]+=f[i-2][j-i];//f[i-2][j-i];
		//	printf("f[%d][%d]=%d\n",i,j,f[i][j]);
		}
	long long ans=0;
	for(int i=k+1;i<=tot;i++)ans+=f[n][i];
	printf("%I64d\n",ans);	
//	system("pause");
}

抱歉!评论已关闭.