[]幸運のビットコンピューティング

幸運

与えられた\(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;
}

おすすめ

転載: www.cnblogs.com/streamazure/p/12585153.html