当前位置: 代码迷 >> 综合 >> D. Rescue Nibel(cf) 区间覆盖 + 组合数学
  详细解决方案

D. Rescue Nibel(cf) 区间覆盖 + 组合数学

热度:99   发布时间:2023-11-23 05:48:23.0

原题链接:Problem - 1420D - Codeforces

题目大意:给你n个灯,和每个等的亮的时间段,问你有多少种可以有k个灯一起亮的种数(如果k = 3而且灯 1 2 3在几个时间点都可以一起亮,只算一种。

思路:用区间覆盖,{l, 1} {r + 1, -1},然后sort,维护时间点内灯的个数。每加进来一个等的时候,种数即为现在一定要这个灯,然后在剩下的灯中(维护的这个时间有的灯)选出k - 1个即为组合数,而且不会重复。

AC代码:

 

#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
typedef pair<int, int> PII;
const double pi = acos(-1.0);
#define rep(i, n) for (int i = 1; i <= (n); ++i)
#define rrep(i, n) for (int i = n; i >= (1); --i)
typedef long long ll;
#define sqar(x) ((x)*(x))const ll M = 998244353;
const int N = 3e5 + 10;
PII a[N << 1];
ll fac[N], invfac[N];inline ll qpow(ll a, ll n, ll p)// 快速幂
{ll ans = 1;while (n){if (n & 1)ans = ans % p * a % p;a = a % p * a % p;n >>= 1;}return ans;
}inline ll inv(ll a, ll p)
{return qpow(a, p - 2, p);
}void init()
{fac[0] = 1;for (int i = 1; i < N; ++i) fac[i] = (fac[i - 1] * i) % M;invfac[N - 1] = inv(fac[N - 1], M);for (int i = N - 2; i >= 0; --i) invfac[i] = (invfac[i + 1] * (i + 1)) % M;
}ll C(int n, int m)
{if (n < m || m < 0) return 0;return fac[n] * invfac[m] % M * invfac[n - m] % M;
}int main()
{int n, k;scanf("%d %d", &n, &k);int cnt = 0;init();rep(i, n){int l, r;scanf("%d%d", &l, &r);a[++cnt] = {l, 1};a[++cnt] = {r + 1, -1};}sort(a + 1, a + 1 + cnt);int num = 0;ll res = 0;rep(i, cnt){if(a[i].second == 1){res = (res + C(num, k - 1)) % M;num++;}else num--;}printf("%lld", res);return 0;
}

不会组合数学模板的去学!!

这里有前几天总结的用逆元快速幂求的模板(题目给的取模的模必须是质数才能用)。拿去不谢:

ll fac[N], invfac[N];inline ll qpow(ll a, ll n, ll p)// 快速幂
{ll ans = 1;while (n){if (n & 1)ans = ans % p * a % p;a = a % p * a % p;n >>= 1;}return ans;
}inline ll inv(ll a, ll p)
{return qpow(a, p - 2, p);
}void init() //注意要在主函数中init()!!!
{fac[0] = 1;for (int i = 1; i < N; ++i) fac[i] = (fac[i - 1] * i) % M;invfac[N - 1] = inv(fac[N - 1], M);for (int i = N - 2; i >= 0; --i) invfac[i] = (invfac[i + 1] * (i + 1)) % M;
}ll C(int n, int m)
{if (n < m || m < 0) return 0;return fac[n] * invfac[m] % M * invfac[n - m] % M;
}

我比较喜欢把模数写为M,如果你喜欢用mod就把M都改成mod