【二进制优化】Codeforces - 1041 - F. Ray in the tube

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/monochrome00/article/details/82735449

题目链接<http://codeforces.com/contest/1041/problem/F>


题意:

在两个反射面上取一点发射一道激光,两个反射面上装了一些传感器,问最多有几个传感器能接收到激光。


题解:

首先,题目给出了反射面的纵坐标,这是没有用的,我们只需要考虑横坐标的距离即可。

然后总体思路是:

1)枚举步长。

2)处理出每个点在此步长下的状态,并用map记录每个状态的数量。

3)再枚举起点(起点只需枚举传感器的位置)计算每个起点下的答案。

后面两个复杂度是在1e5级别的,而第一个的复杂度能够达到1e9。

仔细推敲或者参考题解后就可以发现,步长只需枚举2^{l}的情况,这样复杂度可以降到30。

简单证明一下,如果步长不是2^{l},那么步长可以化为2^{l}*(2*x+1)的形式,很容易发现前者是包含后者的,如果在图上进行模拟的话会更清晰。


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+7;
int n,m,y,a[N],b[N];
map<int,int>aa,bb;
int main(){
    scanf("%d%d",&n,&y);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    scanf("%d%d",&m,&y);
    for(int i=1;i<=m;i++)
        scanf("%d",&b[i]);
    int ans=0;
    if(n) ans++;if(m) ans++;
    int mod=2;
    for(int k=2;k<=30;k++){
        aa.clear(),bb.clear();
        for(int i=1;i<=n;i++)
            aa[a[i]%mod]++;
        for(int i=1;i<=m;i++)
            bb[b[i]%mod]++;
        for(int i=1;i<=n;i++)
            ans=max(ans,aa[a[i]%mod]+bb[(a[i]%mod+mod/2)%mod]);
        for(int i=1;i<=m;i++)
            ans=max(ans,bb[b[i]%mod]+aa[(b[i]%mod+mod/2)%mod]);
        mod*=2;
    }
    printf("%d\n",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/monochrome00/article/details/82735449