codeforces 1041 F : Ray in the tube

  题意:给上下两块玻璃,每块玻璃上有一些关键点,问一条射线最多能反射到多少点。

  考试没有想出来啊。

  显然高度差是没有用的啊,直接枚举反射长度len就行了。

  同一行被反射到的点是 $x+2*k*len(k\epsilon N)$

  不同行被反射到的点是 $x+(2*k-1)*len(k\epsilon N^{*})$

  我们观察这个式子就应当发现len取那些值的时候比较优。

  对于同一行,因为k为任意正整数,所以len为1的时候最优,即相当于除掉了所有的质因子。

  但是对于不同行,$(2*k-1)$是奇数,所以当len除去2时不能保证最优。

  这样结论就是只有$2^k$是最优的了(注意判断len=0的情况)。

  

#include <bits/stdc++.h>
#include <unordered_map>
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
#define for1(a,b,i) for(int i=a;i<=b;++i)
#define FOR2(a,b,i) for(int i=a;i>=b;--i)
using namespace std;
typedef long long ll;
inline int read () {
    int f=1,sum=0;
    char x=getchar();
    for(;(x<'0'||x>'9');x=getchar()) if(x=='-') f=-1;
    for(;x>='0'&&x<='9';x=getchar()) sum=sum*10+x-'0';
    return f*sum;
}

#define M 100005
int n,m;
int a[M],b[M];

unordered_map <int,int> A[30],B[30];

int main () {
    //freopen("a.in","r",stdin);
    n=read(),read();
    for1(1,n,i) a[i]=read();
    m=read(),read();
    for1(1,m,i) b[i]=read();
    
    for1(1,n,i) {
        int now=1;
        for1(0,29,j) now<<=1,++A[j][a[i]%now];
    }
    for1(1,m,i) {
        int now=1;
        for1(0,29,j) now<<=1,++B[j][b[i]%now];
    }
    b[m+1]=2e9;
    
    int h=0,ans=0;
    for1(1,n,i) {
        while (b[h+1]<=a[i]&&h<=m) ++h;
        if(b[h]==a[i]) {ans=2;break;}
    }
    
    for1(1,n,i) {
        int now=1;
        for1(0,29,j) {
            int num=0;
            num+=A[j][a[i]%(2*now)];
            num+=B[j][(a[i]+now)%(2*now)];
            ans=max(ans,num);
            now<<=1;
        }
    }
    for1(1,m,i) {
        int now=1;
        for1(0,29,j) {
            int num=0;
            num+=B[j][a[i]%(2*now)];
            num+=A[j][(a[i]+now)%(2*now)];
            ans=max(ans,num);
            now<<=1;
        }
    }
    //cout<<(double)clock()/CLOCKS_PER_SEC<<endl;
    cout<<ans<<endl;
}
posted @ 2018-09-17 09:41  asd123www  阅读(260)  评论(0编辑  收藏  举报