題解 CF734F 【Anton and School】
阿新 • • 發佈:2019-01-26
n) getc school pen clu 情況 == for tdi 在二進制第\(x\)位出現的次數,此時,我們只需要檢驗——
題解 CF734F 【Anton and School】
傳送門
這種將位運算和普通運算結合起來的題目要拆位來考慮,可以得到\(log_{2}(\)值域\()\)的算法,甚至將值域看成常數。
根據
\(a|b+a \& b=a+b\)
得到
\(b_i+c_i=\Sigma a_i+na_i\)
於是
\(a_i=\frac{b_i+c_i- \Sigma a_i}{n}\)
根據這個式子,直接得到\(a_i\),註意在除的時候判斷整除以免非法情況出現。
此時,我們要判斷\(b_i\)和\(c_i\)是否真的合法,考慮到位運算的性質,我們開個\(cnt[x]\),記錄所有\(a_i\)
\(b_i=2^k \times cnt[k]\)
\(c_i=\Sigma a_i+2^k \times (n-cnt[k])\)
這裏的\(k\)滿足
\(a_i\&(1<<(k-1))\)
總復雜度\(O(nlog(\)值域\())\),相當於\(O(n)\),但理論上會爆\(unsigned\) \(long\) \(long\) 但是它沒有爆。
極其醜陋的代碼
#include<bits/stdc++.h> #define RP(t,a,b) for(register int (t)=(a),edd_=(b);t<=edd_;++t) #define qit return puts("-1"),0 using namespace std;typedef unsigned long long ll; template<class ccf> inline ccf qr(ccf k){ char c=getchar(); ccf x=0; int q=1; while(c<48||c>57)q=c==45?-1:q,c=getchar(); while(c>=48&&c<=57)x=x*10+c-48,c=getchar(); return q==-1?-x:x; } const int maxn=200005; ll a[maxn]; ll b[maxn]; ll c[maxn]; ll cnt[65]; ll n;ll sum; int main(){ #ifndef ONLINE_JUDGE freopen("in.in","r",stdin); freopen("out.out","w",stdout); #endif n=qr(1); RP(t,1,n) b[t]=qr(1ll); RP(t,1,n) c[t]=qr(1ll); RP(t,1,n) sum+=b[t]+c[t]; if(sum%(n<<1)) qit; sum/=(n<<1); RP(t,1,n){ a[t]=b[t]+c[t]-sum; if(a[t]%n) qit;//宏 else a[t]/=n; RP(i,1,63) if((a[t]&(1ll<<(i-1)))) cnt[i]++; } ll temp=0; RP(t,1,n){ temp=0; RP(i,1,63) if(a[t]&(1ll<<(i-1))) temp+=cnt[i]*(1ll<<(i-1)); if(temp!=b[t]) qit;//宏 temp=sum; RP(i,1,63) if(a[t]&(1ll<<(i-1))) temp+=(n-cnt[i])*(1ll<<(i-1)); if(temp!=c[t]) qit;//宏 } RP(t,1,n) cout<<a[t]<<‘ ‘; puts(""); return 0; }
題解 CF734F 【Anton and School】