codeforces 689E

题意: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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值