清北学堂模拟赛d6t4 数组异或
Posted zbtrs
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了清北学堂模拟赛d6t4 数组异或相关的知识,希望对你有一定的参考价值。
分析:直接O(n^3)做是只有50分的,可以加一点小小的优化,就是c[k]可以从c[k-1]得到,但是还是只有60分,从宏观意义上是不能继续优化了。对于这类涉及到位运算的性质的题目,将每个数转化成二进制,两个数第i位异或值为1当且仅当两个数上这一位不同,我们只需要记录每一位上有多少个a为1,有多少个b为1,最后相乘再乘上这一位表示的大小就可以了.
#include<iostream> #include<cstdio> #include<cstring> #define N 100005 #define ll long long #define p 1000000007 using namespace std; int n; ll a[N],b[N],t1[50],t2[50]; ll sum; inline int read() { int x(0),f(1);char c=getchar(); while(c<\'0\'||c>\'9\'){if(c==\'-\')f=-1;c=getchar();} while(c>=\'0\'&&c<=\'9\'){x=x*10+c-\'0\';c=getchar();} return x*f; } inline ll add(ll a,ll b){return a+b>p?(a+b)%p:a+b;} int main() { freopen("xorarray.in","r",stdin); freopen("xorarray.out","w",stdout); n=read(); for(int i=1;i<=n;i++)a[i]=read(); for(int i=1;i<=n;i++)b[i]=read(); for(int i=1;i<=n;i++) { sum=0; for(int k=1;a[i]>=(1<<(k-1))-1;k++)if(a[i]&(1<<(k-1)))t1[k]++; for(int k=1;b[i]>=(1<<(k-1))-1;k++)if(b[i]&(1<<(k-1)))t2[k]++; for(int j=1;j<=31;j++)sum=add(sum,t1[j]*(i-t2[j])*(1<<(j-1))+t2[j]*(i-t1[j])*(1<<(j-1))); cout<<sum<<\' \'; }
return 0; }
以上是关于清北学堂模拟赛d6t4 数组异或的主要内容,如果未能解决你的问题,请参考以下文章