您的位置:首页 > 其它

【bzoj3193】[JLOI2013]地形生成 dp+组合数学

2016-03-01 16:37 176 查看
好难呀!!!

第一问:

从大到小往里插

不考虑相等的情况

第i大的数有min(i,b[i]+1)个位置可以插

考虑相等的情况

把相等的提出来一起处理

min(i,b[i]+1)+j-i

第二问:

把高度相同的放在一起考虑

ans*=tmp

tmp表示这些高度相同的一共多少种放法可以使等高线不同

现在问题是,把n个球放进m个箱子中,第i个球只能放进编号为[1,b[i]]的箱子中,求方案数。

球都是相同的,两个方案不同,当且仅当存在某一个箱子中的球数不同。

dp[i][j]表示前i个物品只排在前j个位置的方案数

dp[i][j]=dp[i-1][j]+dp[i-1][j-2]+dp[i-1][j-3]+……+dp[i-1][1]  (1<=j<=b[i])

dp[i][j]=dp[i-1][j]+dp[i][j-1]

f[i]+=f[i-1] (1<=i<=b[i])

这里要注意!!

要把高度相同的按照b来排序,否则是不能dp的

tmp=∑dp[num][j] (1<=j<=bmax)

把少于看成不超过,WA了一发

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<iostream>
#define mod 2011
#define maxn 1100

using namespace std;

struct yts
{
int h,x;
}a[maxn];

int f[maxn];
int ans1,n,m,ans2;

bool cmp(yts x,yts y)
{
return x.h>y.h || (x.h==y.h && x.x<y.x);
}

int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++) {scanf("%d%d",&a[i].h,&a[i].x);a[i].x--;}
sort(a+1,a+n+1,cmp);
ans1=ans2=1;
for (int i=1,t=1;i<=n;i=++t)
{
while (t<n && a[t+1].h==a[t].h) t++;
memset(f,0,sizeof(f));
f[0]=1;
for (int j=i;j<=t;j++)
{
ans1=ans1*(min(i,a[j].x+1)+j-i)%mod;
for (int k=1;k<=min(i-1,a[j].x);k++) f[k]=(f[k]+f[k-1])%mod;
}
int tmp=0;
for (int j=0;j<=min(i-1,a[t].x);j++) tmp=(tmp+f[j])%mod;
ans2=ans2*tmp%mod;
}
printf("%d %d\n",ans1,ans2);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: