Codeforces 1041F Ray in the tube

题面在这里

题意:一根管道,上下边界分别有一些传感器,射出一条光线在管内反弹,问最多射到多少个传感器上

首先考虑出射点\(x_a\)和第一个反弹点\(x_b\)的横坐标差\(d\)

那么在\(x_a\)所在直线上的\(x_a+d\cdot 2k\)位置会被射到

\(x_b\)所在直线上的\(x_a+d\cdot (2k+1)\)位置会被射到

发现都是\(d\)的奇数/偶数倍

那么显然\(d=2^l,(l\gt 0)\)

然后爆枚\(d\),所有同余\(2d\)的位置都是同时被打到的

示例程序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include<cstdio>
#include<algorithm>
#include<map>
using namespace std;

const int maxn=100005;
int n,m,a[maxn],b[maxn],ty,ans;
map<int,int> numa,numb;
void calc(int l){
numa.clear(); numb.clear();
l++;int p=1; while (l--) p=p*2;
for (int i=1;i<=n;i++) numa[a[i]%p]++;
for (int i=1;i<=m;i++) numb[b[i]%p]++;
for (int i=1;i<=n;i++)
ans=max(ans,numa[a[i]%p]+numb[(a[i]+p/2)%p]);
for (int i=1;i<=m;i++)
ans=max(ans,numa[(a[i]+p/2)%p]+numb[a[i]%p]);
}
int main(){
scanf("%d%d",&n,&ty);
for (int i=1;i<=n;i++) scanf("%d",&a[i]);
scanf("%d%d",&m,&ty);
for (int i=1;i<=m;i++) scanf("%d",&b[i]);
ans=2;
for (int i=0;i<30;i++) calc(i);
printf("%d",ans);
return 0;
}