——《巨齒鯊》
離散成一些開區間;/*如果計數題數大區間少可以考慮這個思路,用組合數計數處理區間*/
用f[i][j][k]表示最後一個取到i這個學校,取值在第j段的,j段裏已經取了k個的方案數;
轉移,考慮前一個取到的學校;
f[i][j][k]=f[i−1][j][k]+f[i−1][j][k−1]∗(len[j]−k+1)/k
f[i][j][1]=f[i−1][j][1]+∑∑f[i−1][j′][k]∗len[j]
其中len[j]表示第j段包含整點個數。
用前綴和優化第二個轉移 {注意這個區間處理,右邊部分+1,小處理避免重複} {同時,前綴和優化只要對每個j記錄一個值即可, 想一想,處理起來麻煩就簡化了,事半功倍}
#include<bits/stdc++.h>
#define rep(i, x, y) for(int i = (x); i <= (y); i++)
#define per(i, x, y) for(int i = (x); i >= (y); i--)
#define N 505
#define ll long long
#define mod 1000000007
using namespace std;
int n, tot, a[N], b[N], num[N<<1], g[N], C[N], inv[N];
int main() {
scanf("%d", &n);
inv[1] = 1; rep(i, 2, n) inv[i] = (ll)(mod-mod/i)*inv[mod%i]%mod;
rep(i, 1, n) {
scanf("%d%d", &a[i], &b[i]);
num[++tot] = a[i]; num[++tot] = b[i]+1;
}
sort(num+1, num+1+tot); tot = unique(num+1, num+1+tot)-num-1;
rep(i, 1, n) {
a[i] = lower_bound(num+1, num+1+tot, a[i])-num;
b[i] = lower_bound(num+1, num+1+tot, b[i]+1)-num;
}
C[0] = 1; g[0] = 1;
rep(j, 1, tot-1) {
int len = num[j+1]-num[j];
rep(i, 1, n) C[i] = (ll)C[i-1]*(len+i-1)%mod*inv[i]%mod;
per(i, n, 1) if(a[i] <= j && j+1 <= b[i]) {
int f = 0, m = 1, c = len;//m是i-p
per(p, i-1, 0) {
f = (f+(ll)c*g[p]%mod)%mod;
if(a[p] <= j && j+1 <= b[p]) c = C[++m];
} g[i] = (g[i]+f)%mod;
}
}
int ans = 0; rep(i, 1, n) ans = (ans+g[i])%mod;
printf("%d\n", ans);
return 0;
}