bzoj3193 [JLOI2013]地形生成
阿新 • • 發佈:2017-12-31
一個數 原理 endif 等高線 int gist line 數據 its
輸入第一行給出山的個數N。接下來N行每行有兩個整數,按照標號從1到N的順序分別給出一座山的高度和關鍵數。
1 2
2 2
Description
最近IK正在做關於地形建模的工作。其中一個工作階段就是把一些山排列成一行。每座山都有各不相同的標號和高度。為了遵從一些設計上的要求,每座山都設置了一個關鍵數字,要求對於每座山,比它高且排列在它前面的其它山的數目必須少於它的關鍵數字。 顯然滿足要求的排列會有很多個。對於每一個可能的排列,IK生成一個對應的標號序列和等高線序列。標號序列就是按順序寫下每座山的標號。等高線序列就是按順序寫下它們的高度。例如有兩座山,這兩座山的一個合法排列的第一座山的標號和高度為1和3,而第二座山的標號和高度分別為2和4,那麽這個排列的標號序列就是1 2,而等高線序列就是3 4. 現在問題就是,給出所有山的信息,IK希望知道一共有多少種不同的符合條件的標號序列和等高線序列。Input
Output
輸出兩個用空格分隔開的數,第一個數是不同的標號序列的個數,第二個數是不同的等高線序列的個數。這兩個答案都應該對2011取模,即輸出兩個答案除以2011取余數的結果Sample Input
21 2
2 2
Sample Output
2 2HINT
對於所有的數據,有1<=N<=1000,所有的數字都是不大於109的正整數。
正解:組合數學+$dp$。
把所有山按照高度從大到小排序,相同的一段單獨處理。
對於第一問,算出每次可以插空的數量直接乘法原理即可。
第二問我們需要一個$dp$,設$f[i][j]$表示放了第$i$座山,$i$在位置$j$的方案數。
那麽第$i+1$座山首先要滿足題目給的條件,然後還要在$i$的後面,於是枚舉$i+1$的位置$k$,轉移即可。
這樣做復雜度是$O(n^{3})$的,我們在$dp$裏加上前綴和優化就能做到$O(n^{2})$了。
1 #include <bits/stdc++.h> 2 #define il inline 3 #define RG register 4 #define ll long long 56 using namespace std; 7 8 struct data{ int h,l; }a[1005]; 9 10 int f[1005][1005],sum[1005],n,ans1,ans2; 11 12 il int gi(){ 13 RG int x=0,q=1; RG char ch=getchar(); 14 while ((ch<‘0‘ || ch>‘9‘) && ch!=‘-‘) ch=getchar(); 15 if (ch==‘-‘) q=-1,ch=getchar(); 16 while (ch>=‘0‘ && ch<=‘9‘) x=x*10+ch-48,ch=getchar(); 17 return q*x; 18 } 19 20 il int cmph(const data &a,const data &b){ 21 if (a.h==b.h) return a.l<b.l; return a.h>b.h; 22 } 23 24 il void work(RG int l,RG int r){ 25 for (RG int i=1;i<=l && i<=a[l].l+1;++i) f[l][i]=1; 26 for (RG int i=1;i<=l;++i) sum[i]=(sum[i-1]+f[l][i])%2011; 27 for (RG int i=l+1,p=2;i<=r;++i,++p){ 28 for (RG int j=1;j<=i && j<=a[i].l+p;++j) f[i][j]=sum[j-1]; 29 for (RG int j=1;j<=i;++j) sum[j]=(sum[j-1]+f[i][j])%2011; 30 } 31 RG int res=0; 32 for (RG int i=1;i<=r;++i) (res+=f[r][i])%=2011; 33 (ans2*=res)%=2011; return; 34 } 35 36 int main(){ 37 #ifndef ONLINE_JUDGE 38 freopen("terrain.in","r",stdin); 39 freopen("terrain.out","w",stdout); 40 #endif 41 n=gi(); 42 for (RG int i=1;i<=n;++i) a[i].h=gi(),a[i].l=gi()-1; 43 sort(a+1,a+n+1,cmph),ans1=ans2=1; 44 for (RG int i=1,j;i<=n;i=j+1){ 45 j=i; while (j<n && a[j+1].h==a[j].h) ++j; work(i,j); 46 for (RG int k=i,l=1;k<=j;++k,++l) (ans1*=min(k,a[k].l+l))%=2011; 47 } 48 cout<<ans1<<‘ ‘<<ans2; return 0; 49 }
bzoj3193 [JLOI2013]地形生成