CodeForces 689E Mike and Geometry Problem (离散化+组合数)

Mike and Geometry Problem

题目链接:

http://acm.hust.edu.cn/vjudge/contest/121333#problem/I

Description

Mike wants to prepare for IMO but he doesn't know geometry, so his teacher gave him an interesting geometry problem. Let's define f([l, r]) = r - l + 1 to be the number of integer points in the segment [l, r] with l ≤ r (say that ). You are given two integers n and k and n closed intervals [li, ri] on OX axis and you have to find:

In other words, you should find the sum of the number of integer points in the intersection of any k of the segments.

As the answer may be very large, output it modulo 1000000007 (109 + 7).

Mike can't solve this problem so he needs your help. You will help him, won't you?

Input

The first line contains two integers n and k (1 ≤ k ≤ n ≤ 200 000) — the number of segments and the number of segments in intersection groups respectively.

Then n lines follow, the i-th line contains two integers li, ri( - 109 ≤ li ≤ ri ≤ 109), describing i-th segment bounds.

Output

Print one integer number — the answer to Mike's problem modulo 1000000007 (109 + 7) in the only line.

Sample Input

Input
3 2
1 2
1 3
2 3
Output
5
Input
3 3
1 3
1 3
1 3
Output
3
Input
3 1
1 2
2 3
3 4
Output
6

Hint

题意:

横轴上有n个区间,每次取其中的k个区间,记录区间交集所覆盖的整点;
问对于所有的区间取法,一共覆盖了多少次整点;

题解:

实际上先求出每个整点被多少个区间所覆盖;
假设某点被m条边覆盖,则C(m, k)即为该点一共被覆盖的次数;
(若 m < k 则说明不可能处于k个区间的交集区);
前提:离散化各点! Map[l]++; Map[r+1]--;

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <vector>
#define LL long long
#define eps 1e-8
#define maxn 201000
#define mod 1000000007
#define inf 0x3f3f3f3f
#define IN freopen("in.txt","r",stdin);
using namespace std;

int n;
LL k;
map<int,int> mp;

LL x,y,gcd;
void ex_gcd(LL a,LL b)
{
    if(!b) {x=1;y=0;gcd=a;}
    else {ex_gcd(b,a%b);LL temp=x;x=y;y=temp-a/b*y;}
}
LL f1[maxn],f2[maxn];
/*分子n!,f[i]为(i!)%mod的值*/
void F1()
{
    f1[0]=1;
    for(int i=1;i<maxn;i++)
        f1[i]=(f1[i-1]*i)%mod;
}
/*分母m!,f[i]为(1/i!)%mod的值--逆元*/
void F2()
{
    f2[0]=1;
    for(int i=1;i<maxn;i++)
    {
        ex_gcd(i,mod);while(x<0) {x+=mod;y-=i;}
        f2[i]=(f2[i-1]*(x%mod))%mod;
    }
}
LL C_m_n(LL m,LL n)
{
    /*ans=m!/(m-n)!n!*/
    LL ans=(((f1[m]*f2[m-n])%mod)*f2[n])%mod;
    return ans;
}

int main(int argc, char const *argv[])
{
    //IN;

    F1(); F2();
    while(scanf("%d %I64d",&n,&k) != EOF)
    {
        mp.clear();
        for(int i=1; i<=n; i++) {
            LL x,y; scanf("%I64d %I64d", &x,&y);
            mp[x]++;
            mp[y+1]--;
        }

        LL last = 0;
        LL ans = 0, cur = 0;
        map<int,int>::iterator it;
        for(it=mp.begin(); it!=mp.end(); it++) {
            LL x = it->first, y = it->second;
            if(cur >= k)
                ans = (ans + C_m_n(cur, k)*(x-last)) % mod;
            last = x;
            cur += y;
        }

        printf("%I64d
", ans);
    }

    return 0;
}

原文地址:https://www.cnblogs.com/Sunshine-tcf/p/5693356.html