——《巨齿鲨》
离散成一些开区间;/*如果计数题数大区间少可以考虑这个思路,用组合数计数处理区间*/
用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;
}