【二進位制優化】Codeforces - 1041 - F. Ray in the tube
阿新 • • 發佈:2018-11-10
題目連結<http://codeforces.com/contest/1041/problem/F>
題意:
在兩個反射面上取一點發射一道鐳射,兩個反射面上裝了一些感測器,問最多有幾個感測器能接收到鐳射。
題解:
首先,題目給出了反射面的縱座標,這是沒有用的,我們只需要考慮橫座標的距離即可。
然後總體思路是:
1)列舉步長。
2)處理出每個點在此步長下的狀態,並用map記錄每個狀態的數量。
3)再列舉起點(起點只需列舉感測器的位置)計算每個起點下的答案。
後面兩個複雜度是在1e5級別的,而第一個的複雜度能夠達到1e9。
仔細推敲或者參考題解後就可以發現,步長只需列舉
簡單證明一下,如果步長不是,那麼步長可以化為的形式,很容易發現前者是包含後者的,如果在圖上進行模擬的話會更清晰。
#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; }