与えられた\(N \)に続いて、整数、\(A_1、A_2、...、 A_N。\)
探している\(\ sum_を1} ^ {N-I = \ sum_ 1} = {J ^ N-(a_iを\&a_j)\)。\(\&\)バイナリ演算子
デュアル循環を考えるのは簡単
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
ans+=(a[i]&a[j]);
時間複雑である\(O(^ N-2)\) 、および\(N - <= 10 5 ^ \) 、タイムアウトしました。
性質および操作を所定の各数値は、いずれかのその後の計算を2進数に変換しています。1が1である場合にのみ、二つの数字は、そうでなければ結果がゼロである、結果である場合にのみ。
サンプルには、例えば、5つの数字進数に入ります
\(00001 \)
\(00010 \)
\(00011 \)
\(00100 \)
\(00101 \)
右端の列の中の([1] \)\(それ自体を含む)、他の数字とAND、3列の結果が得られた場合。\(A [3] \)、\ (A [5] \)の場合と同じ理由。したがって、この列中の全加算結果9。二乗コラム1の数。
法律によれば、他の列、バイナリ表現の和である桁の結果の文字列を計算し続けます。
あなたは捕虜機能でのmath.hを使用することはできませんので、戻り値は、長い長いストレージを必要とするかもしれないので、進数の合計が再書き込み1に、(戻り値の型がdoubleである)、小数の時刻に変換されることに注意してください。
$ \ {色の緑} {} $コードの表示
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<math.h>
using namespace std;
long long a[1005], ans = 0;
long long pow(int base, int n)
{
long long sum=1;
while (n)
{
if (n&1) sum = base*sum;
base *= base;
n >>= 1;
}
return sum;
}
int main() {
long long n, maxc = 0;
cin >> n;
for (int i = 1;i <= n;i++) {
long long num, cnt = 0, nm;
cin >> num;
while (num) {//数num的二进制数中有几位是1
if (num & 1) a[cnt]++;
//num&1不为0,说明num的二进制数中的最右边那位是1
//a[cnt]++表示计数第cnt列的1的个数
cnt++;
num >>= 1;
//相当于num/=2
//num二进制数右移1位
}
maxc = max(maxc, cnt);
//更新最长的二进制数的长度
}
for (int i = 0;i < maxc;i++)
ans += a[i] * a[i] * pow(2, i);
cout << ans;
return 0;
}