Rescue Nibel!(组合数学)

题目链接: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} Cn1m1+ C n − 1 m C_{n-1}^{m} Cn1m,每次增加一盏新的灯就需要增加 C r e s − 1 k − 1 C_{res-1}^{k-1} Cres1k1​,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;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值