1457 又是求和?
题目描述 Description
给出n个整数,第i个数字为a[i],每对数字之间有一个和谐度。每对数字的和谐度定
义为这两个数字的 and,or,xor的和。而所有数的总和谐度是所有数对的和谐度
的和。现在你的任务是对于给定的n个整数,求出它们的总和谐度。
输入描述 Input Description
第一行一个整数n,表示有n个整数。
第2至n + 1行,每行有一个整数a[i],表示第i个数。
输出描述 Output Description
输出一行表示总和谐度。答案保证在263− 1以内。
样例输入 Sample Input
3
1
2
3
样例输出 Sample Output
18
数据范围及提示 Data Size & Hint
1 ≤ n ≤ 1000000,0 ≤ a[i] ≤ 30000.
分类标签 Tags 点此展开
50分TLE代码:
#include<cstdio> #define ll long long using namespace std; const int N=1e6+10; inline const int read(){ register int x=0,f=1; register char ch=getchar(); while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int n,a[N]; ll tot; int main(){ n=read(); for(int i=1;i<=n;i++) a[i]=read(); for(int i=1;i<n;i++){ for(int j=i+1;j<=n;j++){ int t1=a[i]&a[j]; int t2=a[i]|a[j]; int t3=a[i]^a[j]; tot+=t1+t2+t3; } } printf("%lld\n",tot); return 0; }
题解:
首先考虑一下and,or,xor这三种运算对0,1的结果……
0 and 0=0; 0 and 1=0; 1 and 1=1;
0 xor 0=0; 0 xor 1=1; 1 xor 1=0;
0 or 0=0; 0 or 1=1; 1 or 1=1;
可以发现or的值等于and的值与xor的值之和!
显然对于二进制上的每一位如此,对整个数也是如此……因此问题转化为求两两or值之和再乘2。
求两两or值之和的问题直接考虑仍然无从下手,于是还是要按位考虑:
由于两个0或1的数取or的结果为0当且仅当两个数都是0,
因此1~n转化成二进制后每一位的两两or和就是[n(n-1)/2]-[x(x-1)/2],x为这一位为0的数有多少个。
分别求出每一位的两两or和后,简单处理一下再累加就是答案。
AC代码:
#include<cstdio> #define ll long long using namespace std; const int N=1e6+10; inline const int read(){ register int x=0,f=1; register char ch=getchar(); while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int a[N]; ll n,x,now,ans; int main(){ n=read(); for(int i=1;i<=n;i++) a[i]=read(); for(int j=14;j+1;j--){ now=1<<j; x=n; for(int i=1;i<=n;i++) if(a[i]&now) x--; ans+=(now*n*(n-1)>>1)-(now*x*(x-1)>>1); } printf("%lld",ans<<1); return 0; }