Codeforces #361 E. Mike and Geometry Problem 数学

题目

题目链接:http://codeforces.com/contest/689/problem/E

题目来源:Codeforces #361

题解

首先数据比较大,需要离散化。可以一段段考虑。

数轴上一段被选取的次数就和几个集合包含它有关了,算组合数。可以直接做出覆盖次数。

接下来对每段求出组合数累加就行了。

代码

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#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;
}

你可能感兴趣的:(数学)