UPC9575 鑫鑫的算术

题目描述

AK掉五校联考的题目后,鑫鑫在研究二进制在数论中的应用。

鑫鑫给了你n个数,每次你可以从这其中选择两个数a和b,将它们的值分别赋为a and b和a or b(均为二进制位运算)。这样的操作,你可以执行任意多次。鑫鑫希望最终这些数的平方和尽量的大,你能帮他求出这个最大值吗?

输入

第一行一个正整数n,表示数的数量。
第二行n个非负整数,表示鑫鑫给你的n个数。(2≤n≤100000,0≤ai≤108)

输出

一行一个非负整数,表示答案。由于答案太大,你只需要输出答案对998244353(=7×17×223+1,一个质数)取模后的结果。

样例输入

5
1 2 3 4 5

样例输出

99


此类可以操作无限次的题目,一般均与具体的操作执行过程无关,在操作足够次后,会达到一种最优的稳定状态。
在此题中,可以发现,a和b在做题中所给操作前后其二进制各位上1的数目不变,(a、b 和 a&b、a|b 各二进制位上的一的数目相同)。所以题中所给的操作本质上是将一个数某二进制位上的1换到另一个数上。所以我们
可以直接求出所有二进制位上1的数目,然后直接构造组成最大结果的数。

#include "bits/stdc++.h"

using namespace std;
typedef long long ll;
int bit[50];
const int mod = 998244353;

int main() {
    //freopen("input.txt", "r", stdin);
    int n;
    scanf("%d", &n);
    ll temp;
    for (int i = 1; i <= n; i++) {
        scanf("%lld", &temp);
        for (int j = 0; j < 31; j++) {
            if (temp & (1 << j)) {
                bit[j]++;
            }
        }
    }
    ll ans = 0;
    while (n--) {
        temp = 0;
        for (int i = 0; i < 31; i++) {
            if (bit[i] > 0) {
                temp += (1 << i);
                bit[i]--;
            }
        }
        ans = (ans + temp * temp) % mod;
    }
    printf("%lld
", ans);
    return 0;
}
 
原文地址:https://www.cnblogs.com/albert-biu/p/10305696.html