[JLOI2013]地形生成
题目描述
最近IK正在做关于地形建模的工作。其中一个工作阶段就是把一些山排列成一行。每座山都有各不相同的标号和高度。为了遵从一些设计上的要求,每座山都设置了一个关键数字,要求对于每座山,比它高且排列在它前面的其它山的数目必须少于它的关键数字。 显然满足要求的排列会有很多个。
对于每一个可能的排列,IK生成一个对应的标号序列和等高线序列。标号序列就是按顺序写下每座山的标号。
等高线序列就是按顺序写下它们的高度。例如有两座山,这两座山的一个合法排列的第一座山的标号和高度为1和3,而第二座山的标号和高度分别为2和4,那么这个排列的标号序列就是1 2,而等高线序列就是3 4.
现在问题就是,给出所有山的信息,IK希望知道一共有多少种不同的符合条件的标号序列和等高线序列。
输入输出格式
输入格式:
输入第一行给出山的个数N。接下来N行每行有两个整数,按照标号从1到N的顺序分别给出一座山的高度和关键数
输出格式:
输出两个用空格分隔开的数,第一个数是不同的标号序列的个数,第二个数是不同的等高线序列的个数。这两个答案都应该对2011取模,即输出两个答案除以2011取余数的结果
输入输出样例
2 1 2 2 2
2 2
说明
对于所有的数据,有1<=N<=1000,所有的数字都是不大于109的正整数。
首先,考虑第一问:满足条件的编号条件
我们发现高度较小的山对高度较大的山是没有影响的
从大到小排序,这样i就只能放在1~min(i-1,k[i])
又考虑可以排在相同的后面
假设i~j相同,对于每一个j
ans1*=(min(i-1,k[i])+j-i+1)
第二问就是说满足条件的高度排列,即存在重复
可以这样想,f[i][k]前i个相同高度排在前k的方案
f[i][j]=f[i-1][j]+f[i-1][j-1]+f[i-1][j-2]+……+f[i-1][1] (1<=j<=b[i])
f[i][j]=f[i-1][j]+f[i][j-1]
转化为
f[i]+=f[i-1] (1<=i<=b[i])
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<algorithm> 5 using namespace std; 6 struct M 7 { 8 int h,k; 9 }a[10001]; 10 int n; 11 int ans1=1,ans2=1,f[10001]; 12 bool cmp(M x,M y) 13 { 14 return (x.h>y.h||(x.h==y.h&&x.k<y.k)); 15 } 16 int main() 17 {int i,j,k,pos; 18 cin>>n; 19 for (i=1;i<=n;i++) 20 { 21 scanf("%d%d",&a[i].h,&a[i].k); 22 a[i].k--; 23 } 24 sort(a+1,a+n+1,cmp); 25 pos=1; 26 for (i=1;i<=n;i=pos+1) 27 { 28 pos=i; 29 while (a[pos].h==a[pos+1].h&&pos<n) pos++; 30 memset(f,0,sizeof(f)); 31 f[0]=1; 32 for (j=i;j<=pos;j++) 33 { 34 ans1*=min(a[j].k,i-1)+j-i+1; 35 ans1%=2011; 36 for (k=1;k<=min(a[j].k,i-1);k++) 37 { 38 f[k]+=f[k-1]; 39 f[k]%=2011; 40 } 41 } 42 int sum=0; 43 for (k=0;k<=i-1,k<=a[pos].k;k++) 44 sum+=f[k],sum%=2011; 45 ans2*=sum; 46 ans2%=2011; 47 } 48 cout<<ans1<<' '<<ans2<<endl; 49 }