其他分享
首页 > 其他分享> > 生命- DP

生命- DP

作者:互联网

Description

  数轴上有一排N-1棵小树苗,位置分别在1.5,2.5,3.5……,i+0.5,……(N-1)+0.5。
  有一天,由于间田同学施肥过多,小树苗们全部枯死了。但是不要紧,间田同学是魔法师,他掌握着生命的力量。对于一个闭区间内的小树苗,他可以使用魔法复活它们。但是会消耗一定的AP值。消耗的AP值定义为区间右端点减去左端点(右端点大于左端点,即消耗的AP值至少为1)。比如对于区间[3,5]使用魔法,消耗的AP值为5-3=2。
  同时,由于一些无可奉告的原因,每一个端点只能作为一个区间的开头或结尾,且每次施法的左右端点只能是1到N之间的整数。
    

  以上情况合法。
    

  以上情况由于某一个点成为了多个区间的开头或结尾而不合法。
  间田同学有K的AP值,消耗完后他就不能再使用魔法了,即随时保证AP值大于等于0。现在他想知道,他有多少种方案能够将所有小树苗全部复活。
  对于两个方案,如果操作集合相同,则视为两个相同的方案。比如“先复活区间[1,3]的树苗再复活区间[2,4]的树苗”与“先复活区间[2,4]的树苗再复活区间[1,3]的树苗”视为同一种方案。空集不算一个合法方案。
  小树苗可以多次被复活,效果与被复活一次相同,但是没有被魔法波及到的小树苗将一直保持枯死状态。

Input

  第一行两个正整数N,K,代表小树苗的个数与间田同学初始AP值。

Output

  输出一行一个整数,表示使得1到N所有小树苗都复活的方案数(对10^9+7取模)。

Sample Input

4 4

Sample Output

3
【样例解释】
可行不同的操作集合为{[1,4]},{[1,4],[2,3]},{[1,3],[2,4]}。

Hint

【数据规模及约定】
  对于30%的数据,1≤N≤10,1≤K≤50;
  对于40%的数据,1≤N≤14,1≤K≤50;
  对于50%的数据,1≤N≤16,1≤K≤500;
  对于80%的数据,1≤N≤50,1≤K≤500;
  对于90%的数据,1≤N≤50,1≤K≤5000;
  对于100%的数据,1≤N≤100,1≤K≤100000。


思路


代码

#include <iostream>
#include <cstdio>
#define ex 3000
using namespace std;
const int Mod=1e9+7;
int n,K;
long long ans,dp[2][105][6005];
int main()
{
	scanf("%d%d",&n,&K);
	dp[1][1][1+ex]=1;
	for(int i=2;i<=n;++i)
		for(int j=0;j<=i;++j)
			for(int k=0;k<=ex*2;++k)
			{
				dp[i&1][j][k]=0;
				if(j>=1&&k-i>=0) dp[i&1][j][k]=(dp[(i-1)&1][j][k]+dp[(i-1)&1][j-1][k-i])%Mod;//不放+放左
				if((j>=1||i==n)&&k+i<=2*ex) dp[i&1][j][k]=(dp[i&1][j][k]+1LL*dp[(i-1)&1][j+1][k+i]*(j+1)%Mod)%Mod;//放右
			}
	for(int i=0;i>=max(-K,-ex);--i) ans=(ans+dp[n&1][0][i+ex])%Mod;
	printf("%lld\n",ans);
	return 0;
}

标签:小树苗,生命,AP,括号,DP,端点,复活,dp
来源: https://www.cnblogs.com/wuwendongxi/p/13766702.html