【ZROI244丁同学从小就养成了自觉学习的习惯】

其实有很多分是脑残错误导致的(变量名敲错了解一下),也有太弱导致的(本题连n^3dp都没有想出来),不然起码分数*2,还需要提高啊。

题目背景

中国少年先锋队第七次全国代表大会即将在北京召开,经过选拔和审核,来自海盐县实验小学教育集团501班的丁某某同学作为嘉兴市唯一少先队员代表将出席本次大会,他也是海盐县出席全国少代会的第一人。昨天,丁某某起程前往北京参加中国少先队代表大会。

题目描述

当丁某某同学到达北京之后,他在大街上看到了一排n个建筑。令第i个建筑的高度是hi,这个h数组是一个1,2,3,,n1,2,3,,n的排列。把他们排成一排后,定义第i个建筑是前缀最优的当且仅当不存在某个j<i,hj>hi。同样地,我们定义第i个建筑是后缀最优的当且仅当不存在某个j>i,hj>hi。丁某某想要这一排建筑恰好有L个前缀最优和R个后缀最优。 现在丁某某同学想要知道满足条件的解有多少个,答案对109+7取模。

输入格式

第一行三个正整数 n,L,R

输出格式

一行一个整数,表示答案模109+7

样例1

input

5 3 2

output

18

限制与规定

对于 20%的数据,n10 对于70%的数据,n300 对于100%的数据,n500001L,Rn500001L,Rn 时间限制1s 空间限制512 首先,我们看70分的算法(nLR),dp方程,f[i,j,k]表示选了前i大的数出来放,左边有j个满足前缀最优,k个满足后缀最优 根据这个我们就可以得出一个神奇的方程f[i][j][k]=f[i-1][j-1][k]+f[i-1][j][k-1]+f[i-1][j][k]*(n-2)除非新加入的这个小的数放在左右两端,否则对前缀最优后缀最优不会产生贡献。 我们进一步考虑优化,由于左和右的方案可见是对称的,我们考虑只算其中一个再组合数搞出另一个。 那么就有f[i,k]表示放一边,且有k个满足最优前后缀的方案数 方程f[i,k]=f[i-1][k]*(i-1)+f[i-1][k-1] 同理上面的方程 我们枚举第i+1个点为最高点,其左边有i个点,那么此时满足题意可得(0<=i<=n-1) ANS+=C(n-1,i)*F[i,L-1]*F[n-i-1,L-1] 最大值固定,然后C(n-1,i)将i个数分配到最大值左右,然后由于最大值一定满足最优前后缀,那么对于i个数就是L-1,对于n-i-1个数就是R-1.这样就做到n^2搞出来了。 70分code
//70分 code
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
const int mod = 1000000007;
int n,L,R;
int f[305][305][305];
int main()
{
	scanf("%d%d%d",&n,&L,&R);
	f[1][1][1]=1;
	for(int i=2;i<=n;i++)
	{
		for(int j=0;j<=min(L,i);j++)
		{
			for(int k=0;k<=min(R,i);k++)
			{
				if(j>=1) f[i][j][k] = (f[i][j][k]+f[i-1][j-1][k])%mod;
				if(k>=1) f[i][j][k] = (f[i][j][k]+f[i-1][j][k-1])%mod;
				if(i>=2) f[i][j][k] =  (f[i][j][k] +(long long) f[i-1][j][k]*(i-2)%mod)%mod;
			}
		}
	}
	printf("%d",f[n][L][R]);
}
满分code:
#include<iostream>
#include<algorithm>
#define LL (long long)
using namespace std;
const int mod = 1000000007;
const int maxn = 5005;
int fac[maxn],inv[maxn];
int ksm(int a,int b)
{
	int ans = 1;
	for(a%=mod;b;a=LL a*a%mod,b=b>>1)
		if(b&1) ans=LL ans*a%mod;
	return ans;
}
int n,L,R;
int f[maxn][maxn];
int getc(int a,int b)
{
	if(a<b) return 0;
	return LL fac[a]*inv[b]%mod*inv[a-b]%mod;
}
int main()
{
	scanf("%d%d%d",&n,&L,&R);
	fac[0]=1;
	for(int i=1;i<=n;i++) fac[i]=LL fac[i-1]*i%mod;
	inv[n] = ksm(fac[n],mod-2);
	for(int i=n-1;i>=0;i--) inv[i]=LL inv[i+1]*(i+1)%mod;
	f[1][1]=1; f[0][0]=1;
	for(int i=2;i<=n;i++)
	{
		for(int j=0;j<=max(L,R);j++)
		{
			if(j>=1)f[i][j] = (LL f[i-1][j]*(i-1)%mod + f[i-1][j-1] )%mod;
		}
	}
	int ANS = 0;
	for(int i=0;i<=n-1;i++)
	{
		ANS = (ANS+LL getc(n-1,i)*f[i][L-1]%mod*f[n-i-1][R-1]%mod)%mod;
	}
	printf("%d",ANS);
}
 
posted @ 2018-08-03 00:48  Newuser233  阅读(6)  评论(0)    收藏  举报