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; }