题意:给你\(n\)个区间,从这\(n\)区间中选\(k\)个区间出来,要求这\(k\)个区间都要相交.问共有多少种情况.
题解:如果\(k\)个区间都要相交,最左边的区间和最右边的区间必须要相交,即\(min(r[1],...,r[k])>=max(l[1],...,l[k])\).我们先按左边界对所有区间进行排序,然后遍历左边界,遍历到某个区间时,说明这个区间的左边界目前是最大的,然后我们再判断当前左边界(\(l[i]\)就是最大的)和集合中右边界(\(rs.begin()\),一定是满足条件的最小右边界)的关系,用组合数(菜鸡不会组合数,直接套的板子qwq)求个和即可.
-
代码:
ll f[N],invf[N];
ll fpow(ll a,ll k){
ll res=1;
while(k){
if(k&1) res=(res*a)%mod;
k>>=1;
a=a*a%mod;
//cout<<1<<endl;
}
return res;
} void init(int n){
f[0]=1;
for(int i=1;i<=n;++i){
f[i]=f[i-1]*i%mod;
}
invf[n]=fpow(f[n],mod-2);
for(int i=n-1;i>=0;--i){
invf[i]=invf[i+1]*(i+1)%mod;
}
} ll C(int n,int k){
if(k<0 || k>n) return 0;
return f[n]*invf[k]%mod*invf[n-k]%mod;
} struct misaka{
int l,r;
}e[N]; int t;
int n,k; bool cmp(misaka a,misaka b){
if(a.l==b.l) return a.r>b.r;
return a.l<b.l;
} int main() {
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
init(5e5);
cin>>n>>k;
for(int i=1;i<=n;++i){
cin>>e[i].l>>e[i].r;
}
sort(e+1,e+1+n,cmp);
multiset<int> rs;
ll res=0;
for(int i=1;i<=n;++i){
while(!rs.empty() && *rs.begin()<e[i].l){
rs.erase(rs.begin());
//cout<<1<<endl;
}
int cnt=(int)rs.size();
res+=C(cnt,k-1)%mod;
rs.insert(e[i].r);
}
cout<<res%mod<<endl; return 0;
}