标签:lang print scanf 递推 i++ cpp sort 并且 include
由于值域过大,考虑离散化,这样形成若干区间,对于每个人来说每段区间要么全部可选,要么全部不可选。
考虑递推,设 \(f_{i,j}\) 为前 \(i\) 所学校,最后一所参赛学校的数量不超过区间 \(j\) 的方案数,\(g_{i,j}\) 为前 \(i\) 所学校,最后一所参赛学校的数量在区间 \(j\) 的方案数,\(cnt_{i,k,j}\) 为 \(i ... k\) 中可以选区间 \(j\) 的学校个数,按照最前面的选择区间 \(j\) 的学校位置分别统计。
那么区间长度为 \(len\),有 \(cnt\) 个学校可选,并且最左边的学校必选的方案数为:
转移方程:
#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for (int i = (a); i <= (b); i++)
#define per(i, a, b) for (int i = (a); i >= (b); i--)
#define fi first
#define se second
const int N = 505, inf = 0x3f3f3f3f, mod = 1e9 + 7;
typedef pair <int, int> P;
typedef long long LL;
int n, a[N], b[N], v[N<<1], tot;
LL f[N][N<<1], inv[N];
void add_(LL &x, LL y) {
x = x + y >= mod ? x + y - mod : x + y;
}
LL fpow_(LL a, int b) {
LL res = 1;
for (; b; b >>= 1, a = a*a%mod)
if (b&1)
res = res*a%mod;
return res;
}
int main() {
scanf("%d", &n), inv[0] = 1;
rep (i, 1, n) {
scanf("%d%d", &a[i], &b[i]), ++b[i];
v[++tot] = a[i], v[++tot] = b[i];
inv[i] = fpow_(i, mod - 2);
}
sort(v + 1, v + tot + 1);
tot = unique(v + 1, v + tot + 1) - v - 1;
rep (i, 1, n) {
a[i] = lower_bound(v + 1, v + tot + 1, a[i]) - v;
b[i] = lower_bound(v + 1, v + tot + 1, b[i]) - v;
}
tot--;
rep (i, 0, tot)
f[0][i] = 1;
rep (i, 1, n) {
f[i][0] = 1;
rep (j, 1, tot) {
f[i][j] = f[i][j - 1];
int cnt = 0;
LL tmp = 1;
per (k, i, 1)
if (a[k] <= j && j < b[k]) {
cnt++;
tmp = tmp*inv[cnt]%mod*(v[j + 1] - v[j] + cnt - 1)%mod;
add_(f[i][j], f[k - 1][j - 1]*tmp%mod);
}
}
}
printf("%lld\n", (f[n][tot]%mod + mod - 1)%mod);
}
标签:lang print scanf 递推 i++ cpp sort 并且 include
原文地址:https://www.cnblogs.com/ympc2005/p/14023094.html