卧薪尝胆,厚积薄发。
Ray in the tube
Date: Mon Oct 15 00:48:54 CST 2018 In Category: NoCategory

Description:

一个管道,边缘为两条无限长平行直线。边缘上有若干个目标,可以走到任意一个管道的任意一个边缘的整点上 朝对面的一个整点发出激光,激光的轨迹遵循镜面反射,求击中最多能击中多少目标。
$1\leqslant n\leqslant 10^9$

Solution:

手玩一下发现应该会有一些方案是一定劣于另一些方案的,比如 $ \Delta x = 3$ , 它就不如 $ \Delta x = 1 $ 要优,因为 $ \Delta x = 3 $ 的方案选出来的点是 $ \Delta x = 1 $ 的方案选出来的点的真子集,又发现如果 $\Delta x=kw$ ,其中 $k$ 是一个奇数,那么这个也是没用的,因为 $\Delta x=w$ 选的点一定包含他,所以只有二的幂是有用的,然会就只要 $\log_210^9$ 的枚举一下二的幂,然后统计就行了,统计可以开个桶记录一下对 $2\Delta x$ 取模的个数。

Code:


#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<map>
#include<cctype>
#include<cstring>
using namespace std;
inline int read()
{
register int res = 0,f = 1;
register char c = getchar();
while(!isdigit(c))
{
if(c == '-')f = -1;
c = getchar();
}
while(isdigit(c))
{
res = (res << 1) + (res << 3) + c - '0';
c = getchar();
}
return res * f;
}
int n,m;
#define MAXN 100010
int x1[MAXN],x2[MAXN];
map<int,int> p;
int main()
{
n = read();read();
for(int i = 1;i <= n;++i)x1[i] = read();
m = read();read();
for(int i = 1;i <= m;++i)x2[i] = read();
int ans = 0;
for(int i = 1;i <= n;++i)p[x1[i]] = 1;
for(int i = 1;i <= m;++i)if(p.find(x2[i]) != p.end())ans = 2;
for(int cur = 1;cur <= 1000000000;cur *= 2)
{
p.clear();
for(int i = 1;i <= n;++i)++p[x1[i] % (2 * cur)];
for(int i = 1;i <= m;++i)++p[(x2[i] + cur) % (2 * cur)];
for(map<int,int>::iterator it = p.begin();it != p.end();++it)
ans = max(ans,it -> second);
}
cout << ans << endl;
return 0;
}
In tag: 玄学
Copyright © 2020 wjh15101051
ღゝ◡╹)ノ♡