题目
题目链接:http://codeforces.com/contest/689/problem/E
题目来源:Codeforces #361
题解
首先数据比较大,需要离散化。可以一段段考虑。
数轴上一段被选取的次数就和几个集合包含它有关了,算组合数。可以直接做出覆盖次数。
接下来对每段求出组合数累加就行了。
代码
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <stack>
#include <queue>
#include <string>
#include <vector>
#include <set>
#include <map>
#define fi first
#define se second
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
// head
const int N = 2e5+5;
const int MOD = 1e9+7;
int l[N], r[N];
int sum[N*2];
int disc[N*2];
int fac[N];
int n, k;
LL powmod(LL a,LL b) {LL res=1;a%=MOD;for(; b; b>>=1){if(b&1)res=res*a%MOD;a=a*a%MOD;}return res;}
LL inverse(LL a) {return powmod(a, MOD-2);}
int C(int n, int m) {
if (n < m) return 0;
return (LL)fac[n] * inverse(fac[m]) % MOD * inverse(fac[n-m]) % MOD;
}
int main() {
fac[0] = 1;
for (int i = 1; i < N; i++) {
fac[i] = ((LL)fac[i-1] * i) % MOD;
}
while (scanf("%d%d", &n, &k) == 2) {
int tot = 0;
for (int i = 0; i < n; i++) {
scanf("%d%d", l+i, r+i);
disc[tot++] = l[i];
disc[tot++] = ++r[i];
}
sort(disc, disc + tot);
tot = unique(disc, disc + tot) - disc;
for (int i = 0; i < n; i++) {
int l = lower_bound(disc, disc + tot, ::l[i]) - disc;
int r = lower_bound(disc, disc + tot, ::r[i]) - disc;
sum[l]++;
sum[r]--;
}
int ans = 0;
for (int i = 1; i < tot; i++) {
sum[i] += sum[i-1];
ans = (ans + (LL)C(sum[i-1], k) * (disc[i] - disc[i-1])) % MOD;
}
printf("%d\n", ans);
memset(sum, 0, sizeof sum);
}
return 0;
}