CF1041F Ray in the tube
首先 y 肯定是没用的
看到数据范围,
二分?没啥好二分的
dp ? 反正我的状态是存不下的
于是开始手玩
先看看符合条件的点集有什么限制
设点s1, s2, s3, ..., sn 能被同一条射线照到
则它们之间的坐标关系应该以下两条中的一个满足:
- s2 - s1 = s3 - s2
- s2 - s1 = 2(s3 - s2)
观察上面的式子,与它在同一列的点和它的关系满足条件 1 ,
不同列的点和它的关系满足条件 2
那么其实就是求这个式子:
maxnx=1 {∑xi=1[(sx - si) / 2 = (2 * k + 1) * Δ] + ∑xj=1[(sx - sj) / 2 = 2 * k * Δ]}
又经过长时间的手玩,突然想到,我应该会有一些方案是一定劣于另一些方案的
比如 Δx = 3, 它就不如 Δx = 1 要优,
因为 Δx = 3 的方案选出来的点是 Δx = 1 的方案选出来的点的真子集
考虑若要一个方案比当前某个方案劣的话, 则它选出来的点是当前方案选的点的真子集,
而要满足这个条件的话,
设当前方案每一次反射 x 坐标偏移量为 Δx ,那么这个劣的方案的 Δx' = (2 * k + 1) * Δx
联想到 bzoj2734集合选数 的构造的方式,列出以下矩阵:
1, 3, 5, 7, 9, 11, 13, 15...
2, 6, 10, 14, 18, 22, 26, 30, ...
4, 12, 20, 28, 36, 44, 52, 60, ...
...
多画几次认为上面的矩阵是没有问题的,相邻两行的方案之间没有包含关系
其实有意义的 Δx 就是 1, 2, 4, 8, ...
所以有意义的 Δx 只有 log(1e9) 个
考虑 dp,空间可行,并不会转移,也不会预处理
于是做到这里我就弃疗了... => 以下来思路自题解
对于固定的 Δx ,同一列的能作为答案的点集在模 Δx 意义下是同余的
那么对于不同列的点,其实它们的坐标减去或加上一个 Δx 就和另一列的点坐标相同了
所以我们就可以在 O(n*logn*log(1e9)) 的时间内做这道题了
log(1e9) 的枚举 Δx = 2^i
之后 nlogn 的将每个数模 Δx ,钦定一列是加(减容易出锅) Δx 之后再模的
将结果 哈希/离散化/map 存一下每次 ++计数器 统计一个 max 就好了
根本没往模那想,显然对于一些等差的东西,模公差是同余的
代码:
#include<algorithm> #include<iostream> #include<cstring> #include<cstdlib> #include<cctype> #include<cstdio> #include<map> using namespace std; const int MAXN = 100005; int n[2], y[2]; int x[2][MAXN]; inline int rd() { register int x = 0; register char c = getchar(); while(!isdigit(c)) c = getchar(); while(isdigit(c)) { x = x * 10 + (c ^ 48); c = getchar(); } return x; } inline void init() { for(int i = 0; i < 2; ++i) { n[i] = rd(); y[i] = rd(); for(int j = 1; j <= n[i]; ++j) x[i][j] = rd(); } return; } int main() { init(); if(n[0] == n[1] && n[0] == 1 && x[0][1] == x[1][1]) { puts("2"); return 0; } int ans = 0; for(int i = 1; i <= 1000000000; i <<= 1) { int dlt = (i << 1); map<int,int> mp; for(int j = 0; j < 2; ++j) { int pls = (j ? i : 0); for(int k = 1; k <= n[j]; ++k) { ++mp[(x[j][k] + pls) % dlt]; } } for(map<int,int>::iterator it = mp.begin(); it != mp.end(); ++it) ans = max(ans, it->second); } printf("%d\n", ans); return 0; }
题解中证明只有 log(1e9) 个有意义的 Δx 方式是反证
令 Δx = m * 2^i 且 m 为奇数
其实这个方案选的点在 Δx' = Δx / m 的方案中也都选了
听起来比我的证明更加理性一些