题意:n个区间,找出任意k各区间重叠区间长度的和。
题解:从重叠部分考虑,原问题变成每个数字被多少组k区间包含。然后就是扫描区间,组合数计算。
#include<bits/stdc++.h>
typedef long long LL;
using namespace std;
typedef pair<int,int> pii;
#define MOD 1000000007
LL powMod(LL x,LL p,LL mod){
LL ret = 1;
while(p){
if(p&1){
ret = ret*x%mod;
}
x = x*x%mod;
p>>=1;
}
return ret;
}
int main(){
ios_base::sync_with_stdio(0);
int n,m;
while(cin>>n>>m){
vector<int> d1(n),d2(n),d;
for(int i=0;i<n;i++){
cin>>d1[i]>>d2[i];
d.push_back(d1[i]);
d.push_back(d2[i]);
}
sort(d1.begin(),d1.end());
sort(d2.begin(),d2.end());
sort(d.begin(),d.end());
d.resize(unique(d.begin(),d.end())-d.begin());
vector<LL> ss(n+1);
ss[0]=1;
for(int i=1;i<=n;i++){
ss[i] = ss[i-1]*i%MOD;
}
LL ret = 0;
int pc = 0;
for(int i=0,j=0,k=0;k<(int)d.size();k++){
if(k>=1){
if(pc>=m&&d[k]-d[k-1]>1){
// cout<<ss[pc]<<"/"<<ss[m]<<"/"<<ss[pc-m]<<endl;
LL cnm = ss[pc]*powMod(ss[m]*ss[pc-m]%MOD,MOD-2,MOD)%MOD;
ret = (ret + cnm*(d[k]-d[k-1]-1)%MOD)%MOD;
// cout<<"C("<<pc<<","<<m<<"):"<<cnm<<endl;
}
}
while(i<(int)d1.size()&&d1[i]<=d[k]){
pc++;
i++;
}
//cout<<"PC:"<<pc<<endl;
if(pc>=m){
LL cnm = ss[pc]*powMod(ss[m]*ss[pc-m]%MOD,MOD-2,MOD)%MOD;
ret = (ret + cnm)%MOD;
// cout<<"C("<<pc<<","<<m<<"):"<<cnm<<endl;
}
//cout<<"PC:"<<pc<<endl;
while(j<(int)d2.size()&&d2[j]<=d[k]){
pc--;
j++;
}
}
cout<<ret<<endl;
}
return 0;
}