【JLOI2013】地形生成
先考慮第一個問題(先假設沒有山高度相同)
我們把所有山按高度從大到小排序,設這個集合為S,設一個空集合為V,
我們把山按順序放入集合V。
考慮第i座山插進去的時候能放的位置,因為現在前面有i - 1座山比它高,再加上本來的第i個位置,它一共有i個位置可以放。這個山的關鍵值如果為k,它只能在前min(k,i)個位置里挑。
所以第i個山的放的位置的組合為ci = min(k,i)種。ans = c1 * c2 …… * cn;
但是我們現在有山的高度相同,且關鍵值不同。兩座高度相同的山能放的最靠后的位置,一定是關鍵值大的那個越靠后。所以我們先按高度從大到小,然后高度相同的關鍵值從小到大排序出S集合。
設[x,y]這段區間的山高度相同。所以 ci = min(x,k) + i - x。因為一座山在滿足關鍵值的情況下,可以也放在高度相同的山前面。
所以最后 得出 ans1 = c1 * c2 …… * cn;
接下來為第二個問題:
我們每次都把高度相同的一起加入,
我們考慮把這個問題轉化成最經典的球盒模型,大致能搞成這個樣子:
把n個沒有標號的球放進m個盒子里,允許有盒子為空,但是第i個球只能放到前pi個盒子里,我們把pi從小到大排序后,可以強行規定pi小的只能出現在pi大的球之前,這樣就變成了無標號的了。
于是就有一個dp,設f[i][j]表示第i個球嚴格放在第j個盒子里的方案數
f[i][j]=∑k=1~j f[i-1][k]?
因為f[i][j-1]=∑k=1~j-1 f[i-1][k]
所以f[i][j] = f[i - 1][j] + f[i][j - 1]?
我們再用滾動數組,得最終方程
f[i]=f[i]+f[i-1]
[x,y]這一段的方案數為c= f[1] + f[2] +……f[min(a[y].key,x) ]
最后再將每個c連乘就可以啦
*以上部分經過他人借見,感謝!
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> using namespace std; struct node{int h,key;}a[1005]; const int mod=2011; int n,f[1005]; bool cmp(const node &a,const node &b){return a.h>b.h||(a.h==b.h&&a.key<b.key);} void work1() {int i,j,k;sort(a+1,a+n+1,cmp);int num=0,ans1=1;for(i=1;i<=n;i++){if(a[i].h!=a[i-1].h)num=i;//num記錄相同高度的一段的開頭 ans1=(ans1*(min(a[i].key,num)+i-num))%mod;}printf("%d ",ans1); } void work2() {int i,j,k,pos,sum,ans2=1;for(i=1;i<=n;i=pos+1){memset(f,0,sizeof(f));f[1]=1;pos=i;while(pos<=n&&a[i].h==a[pos].h)pos++;pos--;//a[i].h~a[pos].h相同 for(j=i;j<=pos;j++)for(k=2;k<=min(a[j].key,i);k++)f[k]=(f[k-1]+f[k])%mod;sum=0;for(j=1;j<=min(a[pos].key,i);j++)sum=(sum+f[j])%mod;ans2=(ans2*sum)%mod; }printf("%d",ans2); } int main() {int i,j,k;scanf("%d",&n);for(i=1;i<=n;i++)scanf("%d%d",&a[i].h,&a[i].key);work1();work2();return 0; }轉載于:https://www.cnblogs.com/dsb-y/p/11205867.html
總結
以上是生活随笔為你收集整理的【JLOI2013】地形生成的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CUDA编程中内存管理机制
- 下一篇: pycharm设置字体和背景色