P7156 [USACO20DEC] Cowmistry P 题解
先令 \(k\rightarrow k + 1\)。
设 \(m\) 表示 \(k\) 二进制的最高位的下一位幂次,不难发现 \([0,m), [m,2m)\) 中不能同时选,不然就一定会有 \(2^m> k\),
所以分别考虑每个长度 \(m\) 的段,继续考虑 \(m' = m/2\),如果三个数同时选到了 \([0,m')\) 中那么限制就没有了,在这个区间里任选三个数即可,右边同理,否则一定有一侧选择了两个,另一侧一个。
不失一般性,设右边有一个,左边两个之间是没有约束的,只需要计算出 \(c\) 表示右边每一个数有多少种左边的数与之对应即可,所以对于右边的这一个数 \(\binom{c}{2}\) 就是答案。
我们考虑分治下去,设左右区间分别为 \([l1,r1), [l2,r2)\)。
首先如果 \(k\) 这一位上是 \(0\) 的话,强制两边这一位都选择同 0 或同 1,直接递归下去。
否则如果两个这一位相同,那么对后面位没有限制,将左侧的数的个数计入 \(c\) 中递归下去。
终止条件是左侧区间全部都不/存在,如果都不存在,显然结束了,如果都存在,那么右侧所有数对应的 \(c\) 都是一样的,都是 \(k\bmod (r1-l1)\)。
时间复杂度 \(O(k\log k)\)。
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#include <set>
#include <map>
#define x first
#define y second
#define int long long
using namespace std;
typedef pair<int, int> PII;
const int N = 1e5 + 10, INF = 1e18, mod = 1e9 + 7;
bool Mst;
int n, k, idx, s[N], ans;
PII p[N], tmp[N];
int C3(int n) {
return (__int128)n * (n - 1) * (n - 2) / 6 % mod;
}
int C2(int n) {
return n * (n - 1) / 2 % mod;
}
bool in(int l, int r) {
int t = lower_bound(p + 1, p + n + 1, (PII){r, -1}) - p;
if(t <= n && p[t].x <= l) return 1;
return 0;
}
int calc(int x) {
int pos = lower_bound(p + 1, p + n + 1, (PII){x + 1, -1}) - 1 - p;
if(pos == 0) return 0;
return s[pos - 1] + min(p[pos].y, x) - p[pos].x + 1;
}
int calc(int l, int r) {
return (calc(r) - calc(l - 1));
}
int judge(int l, int r) {
int t = calc(l, r);
if(t == r - l + 1) return 1;
if(t == 0) return 0;
return -1;
}
void solve(int b, int l1, int r1, int l2, int r2, int coef) {
// if(l2 == r2) return ;
// cout << l1 << ' ' << r1 << ' ' << l2 << ' ' << r2 << endl;
if(judge(l1, r1 - 1) == 0) {
ans = (ans + calc(l2, r2 - 1) * C2(coef)) % mod;
return ;
}
if(judge(l1, r1 - 1) == 1) {
ans = (ans + C2(coef + k % (r2 - l2)) * calc(l2, r2 - 1)) % mod;
return ;
}
int m1 = l1 + r1 >> 1, m2 = l2 + r2 >> 1, L = calc(l1, m1 - 1), R = calc(m1, r1 - 1);
// cout << k << ' ' << b << ' ' << (k >> b & 1) << '\n';
if(k >> b & 1) {
solve(b - 1, l1, m1, m2, r2, coef + R);
solve(b - 1, m1, r1, l2, m2, coef + L);
}
else {
solve(b - 1, l1, m1, l2, m2, coef);
solve(b - 1, m1, r1, m2, r2, coef);
}
}
bool Med;
signed main() {
// freopen("dat.in", "r", stdin);
ios::sync_with_stdio(0), cin.tie(0);
cerr << abs(&Mst - &Med) / 1048576.<< "Mb\n";
cin >> n >> k, k ++;
int m = 1;
while(m <= k) m <<= 1;
int tot = 0, cnt = 0;
for(int i = 1; i <= n; i ++) cin >> p[i].x >> p[i].y;
sort(p + 1, p + n + 1);
for(int i = 1; i <= n; i ++) {
if(idx && tmp[idx].y == p[i].x - 1) tmp[idx].y = p[i].y;
else tmp[++ idx] = p[i];
}
swap(n, idx), swap(p, tmp);
for(int i = 1; i <= n; i ++) s[i] = s[i - 1] + (p[i].y - p[i].x + 1);
// cout << m << '\n';
for(int i = 0; i <= p[n].y; i += m) {
int mid = i + m / 2;
ans = (ans + C3(calc(i, mid - 1)) + C3(calc(mid, i + m - 1))) % mod;
solve(__lg(m) - 2, i, mid, mid, i + m, 0);
solve(__lg(m) - 2, mid, i + m, i, mid, 0);
}
cout << ans << '\n';
return 0;
}

QwQ
浙公网安备 33010602011771号