题目链接:Problem - 1420D - Codeforces Rescue Nibel!
有 n n n盏灯,每盏灯亮在一个连续的时间段亮着,求恰好有 k k k盏灯亮着的组合数,需要取模。这道题咋一看有点像扫描线,最终的做法也是类似扫描线的,按照下标排序从小到大排序,下标相等按权值从大到小排。然后扫一遍进行计数。计数的时候我们需要用到组合数的公式, C n m C_n^m Cnm= C n − 1 m − 1 C_{n-1}^{m-1} Cn−1m−1+ C n − 1 m C_{n-1}^{m} Cn−1m,每次增加一盏新的灯就需要增加 C r e s − 1 k − 1 C_{res-1}^{k-1} Cres−1k−1,res表示当前亮着灯的数量。这道题好需要组合数的计算公式,以及快速幂求逆元。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=3e5+5;
const int mod=998244353;
int n,k;
ll fac[N];
struct node{
int val,idx;
node(){
}
node(int x,int y){
idx=x,val=y;
}
bool operator<(const node &A)const{
if(idx==A.idx) return val>A.val;
return idx<A.idx;
}
}t[N<<1];
ll qsm(ll a,ll b){
ll res=1;
while(b){
if(b&1) res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res;
}
ll cm(ll x,ll y){
if(x==y) return 1;
return fac[y]*qsm(fac[x],mod-2)%mod*qsm(fac[y-x],mod-2)%mod;
}
int main(){
scanf("%d%d",&n,&k);
fac[0]=fac[1]=1;
for(int i=2;i<=n;i++){
fac[i]=(fac[i-1]*i)%mod;
//cout<<fac[i]<<endl;
}
int ct=0;
for(int i=1,x,y;i<=n;i++){
scanf("%d%d",&x,&y);
t[++ct]=node(x,1);
t[++ct]=node(y,-1);
}
sort(t+1,t+ct+1);
// for(int i=1;i<=ct;i++){
// printf("##%d %d\n",t[i].idx,t[i].val);
// }
ll ans=0,res=0;
for(int i=1;i<=ct;i++){
if(t[i].val==1){
res++;
if(res>=k){
ans=(ans+cm(k-1,res-1))%mod;
}
}
else res--;
}
printf("%lld\n",ans);
return 0;
}