1. 程式人生 > >UOJ#204 【APIO2016】Boat

UOJ#204 【APIO2016】Boat

submit word namespace content bmi string 參加 預處理 兩個

Time Limit: 70 Sec Memory Limit: 256 MB
Submit: 559 Solved: 248

Description

在首爾城中,漢江橫貫東西。在漢江的北岸,從西向東星星點點地分布著個劃艇學校,編號依次為到。每個學校都 擁有若幹艘劃艇。同一所學校的所有劃艇顏色相同,不同的學校的劃艇顏色互不相同。顏色相同的劃艇被認為是一 樣的。每個學校可以選擇派出一些劃艇參加節日的慶典,也可以選擇不派出任何劃艇參加。如果編號為的學校選擇 派出劃艇參加慶典,那麽,派出的劃艇數量可以在Ai至Bi之間任意選擇(Ai<=Bi)。值得註意的是,編號為i的學 校如果選擇派出劃艇參加慶典,那麽它派出的劃艇數量必須大於任意一所編號小於它的學校派出的劃艇數量。輸入 所有學校的Ai、Bi的值,求出參加慶典的劃艇有多少種可能的情況,必須有至少一艘劃艇參加慶典。兩種情況不同 當且僅當有參加慶典的某種顏色的劃艇數量不同

Input

第一行包括一個整數N,表示學校的數量。接下來N行,每行包括兩個正整數,用來描述一所學校。其中第行包括的

兩個正整數分別表示Ai,Bi(1<=Ai<=Bi<=10^9),N<=500

Output

輸出一行,一個整數,表示所有可能的派出劃艇的方案數除以1,000,000,007得到的余數

Sample Input

2
1 2
2 3

Sample Output

7

HINT

Source

動態規劃

看著題解懵X一個多小時,我這麽弱已經沒救了吧

枚舉數量顯然無力,我們得考慮將整段區間一起處理,於是先將區間離散化

將派船看作在限定區間裏選一個數,設f[i][j][k]表示當前枚舉到第i個學校,最大船數在第j段,這段裏選了k個數的方案數。

$ f[i][j][k]=f[i-1][j][k]+f[i-1][j][k-1]* \frac {C(len[j],k)}{C(len[j],k-1)} $

特殊處理 $ f[i][j][1]=f[i-1][j][1] + (\sum_{a=1}^{j-1} \sum_{k=0}^{i-1} f[i-1][a][k] )*len[j] $

第一維可以滾動優化掉

第一個式子的組合數,約分一下變成了(len-k+1)/k ,預處理500以內的逆元即可。

第二個式子用前綴和優化。

然後大概就能過了

 1 #include<iostream>
 2 #include<cstdio>
 3
#include<cstring> 4 #include<algorithm> 5 #define LL long long 6 using namespace std; 7 const int mod=1e9+7; 8 const int mxn=1105; 9 int read(){ 10 int x=0,f=1;char ch=getchar(); 11 while(ch<0 || ch>9){if(ch==-)f=-1;ch=getchar();} 12 while(ch>=0 && ch<=9){x=x*10+ch-0;ch=getchar();} 13 return x*f; 14 } 15 int inv[mxn]; 16 void init(){ 17 inv[0]=inv[1]=1; 18 for(int i=2;i<mxn;i++){ 19 inv[i]= ((-mod/i)*(LL)inv[mod%i]%mod+mod)%mod; 20 } 21 return; 22 } 23 int n; 24 int c[mxn][mxn]; 25 struct seg{ 26 int L,R; 27 }a[mxn]; 28 int pos[mxn],sz=0,len[mxn]; 29 int f[mxn][mxn],g[mxn]; 30 int num[mxn]; 31 int main(){ 32 // freopen("boat.in","r",stdin); 33 // freopen("boat.out","w",stdout); 34 int i,j; 35 n=read(); 36 init(); 37 for(i=1;i<=n;i++){ 38 a[i].L=read()-1;a[i].R=read(); 39 pos[++sz]=a[i].L;pos[++sz]=a[i].R; 40 } 41 sort(pos+1,pos+sz+1); 42 sz=unique(pos+1,pos+sz+1)-pos-1; 43 // for(i=1;i<=sz;i++)printf("%d",pos[i]); 44 for(i=1;i<=n;i++){ 45 a[i].L=lower_bound(pos+1,pos+sz+1,a[i].L)-pos; 46 a[i].R=lower_bound(pos+1,pos+sz+1,a[i].R)-pos; 47 } 48 for(i=1;i<=sz;i++)len[i]=pos[i]-pos[i-1]; 49 f[0][1]=1; 50 for(i=1;i<=sz;i++)g[i]=1; 51 for(i=1;i<=n;i++){ 52 for(j=a[i].L+1;j<=a[i].R;j++){ 53 num[j]++; 54 for(int k=num[j];k>1;k--) 55 f[j][k]=((LL)f[j][k]+(LL)f[j][k-1]*(len[j]-k+1)%mod*(LL)inv[k])%mod; 56 f[j][1]=((LL)f[j][1]+(LL)g[j-1]*len[j]%mod)%mod; 57 } 58 for(j=a[i].L+1;j<=sz;j++){ 59 g[j]=g[j-1]; 60 for(int k=num[j];k;k--){ 61 g[j]=((LL)g[j]+f[j][k])%mod; 62 } 63 } 64 } 65 g[sz]--;if(g[sz]<=0)g[sz]+=mod; 66 printf("%d\n",g[sz]); 67 return 0; 68 }

UOJ#204 【APIO2016】Boat