1 条题解

  • 0
    @ 2026-8-27 22:44:10

    这道题是一道经典的**按位贡献(位运算拆分)**问题。

    解题思路:

    异或运算(XOR)的性质是:相同为0,不同为1

    我们可以分开计算二进制每一位对答案的贡献。 对于第 kk 位(权值为 2k2^k):

    • 设数组中这一位为 1 的数字个数为 cnt1
    • 那么这一位为 0 的数字个数即为 cnt0 = N - cnt1
    • 要使两个数异或后第 k 位为 1,必须一个数是 0,另一个数是 1。
    • 能够组成这样不同数对的组合数为 cnt0 * cnt1

    因此,第 kk 位对总和的贡献为:cnt0cnt12kcnt0 · cnt1 · 2^k。 将二进制每一位的贡献累加起来,就是最终答案。

    #include <bits/stdc++.h>
    #define int long long
    using namespace std;
    
    int T = 1;
    const int N = 3e5 + 1, B = 60;//坏习惯,考场上记得多加点
    const int MOD = 1e9 + 7;
    int n;
    int arr[N];
    
    //慢速乘(也叫快速乘),防止溢出,顺便装一下,直接使用乘即可
    int MulSlowly(int a, int b) {
    	if (a == 0 || b == 0) return 0;
    	int ans = 0;
    	while (b) {
    		if (b & 1) {
    			ans = (ans + a) % MOD;
    		}
    		a = (a + a) % MOD;
    		b >>= 1;
    	}
    	return ans;
    }
    
    void Solve() {
    	cin >> n;
    	for (int i = 1; i <= n; i++) {
    		cin >> arr[i];
    	}
    	int ans = 0;
    	for (int k = 0; k <= B; k++) {
    		int cnt1 = 0;
    		for (int j = 1; j <= n; j++) {
    			if ((1ll << k) & arr[j]) {
    				cnt1++;
    			}
    		}
    		int cnt0 = n - cnt1;
    		ans = (ans + MulSlowly(MulSlowly(cnt0, cnt1), (1ll << k))) % MOD;
    	}
    	cout << ans;
    }
    
    signed main() {
    	ios::sync_with_stdio(false);
    	cin.tie(0);
    	cout.tie(0);
    	
    	while (T--) {
    		Solve();
    	}
    	return 0;
    }
    
    • 1

    信息

    ID
    1827
    时间
    2000ms
    内存
    1024MiB
    难度
    普及+/提高-
    标签
    递交数
    1
    已通过
    1
    上传者