1 条题解

  • 1
    @ 2026-10-8 20:07:16

    把原式拆成 max⁡(ai,aj)\max(a_i,a_j) 和 (ai&aj)(a_i\&a_j)。

    先将 aa 排序。排序后对 j<ij<i 有 max⁡(ai,aj)=ai\max(a_i,a_j)=a_i,所以总和为:

    ∑i=1nai×∑j<i(ai&aj)\sum_{i=1}^{n} a_i \times \sum_{j<i} (a_i \& a_j)

    接下来快速算 ∑j<i(ai&aj)\sum_{j<i}(a_i\&a_j)。

    按二进制位统计:维护 cnt[k] 表示已加入的数中第 kk 位为 11 的个数。
    处理 aia_i 时,枚举它所有为 11 的位,若该位权值为 ww,则贡献为:

    cnt[w]×wcnt[w] \times w

    累加得到 ∑j<i(ai&aj)\sum_{j<i}(a_i\&a_j),然后:

    ans←ans+ai×该和ans \gets ans + a_i \times \text{该和}

    最后把 aia_i 的各位加入 cnt。

    复杂度:排序 O(nlog⁡n)O(n\log n),枚举二进制位 O(30n)O(30n),总 O(nlog⁡n)O(n\log n)。空间 O(n)O(n),但我代码里偷了个懒,使用了map。

    注意:按位与要加括号;取模;用 long long。

    //T2 正解 100 pts
    #include<bits/stdc++.h>
    using namespace std;
    
    #define int long long
    const int N=1e5+5;
    const int MOD=1e9+7;
    
    int n;
    int a[N];
    unordered_map<int,int> bit;
    
    int lowbit(int x){
        return -x&x;
    }
    
    void add(int x){
        while(x){ 
            bit[lowbit(x)]++;
            x-=lowbit(x);
        }
    }
    
    signed main(){
        freopen("andsum.in","r",stdin);
        freopen("andsum.out","w",stdout);
        cin>>n;
        for(int i=1;i<=n;i++) cin>>a[i];
        sort(a+1,a+1+n);
        int ans=0;
    
        for(int i=1;i<=n;i++){
            int tmp=a[i],res=0;
            while(tmp){ 
                res=(res+bit[lowbit(tmp)]*lowbit(tmp)%MOD)%MOD;
                tmp-=lowbit(tmp);
            }
            ans=(ans+a[i]*res%MOD)%MOD;
            add(a[i]);
        }
        cout<<ans;
    }
    

    感谢deepseek帮我优化Katex公式并修改了一些不通顺的句子,题解AI率 10%

    • 1

    信息

    ID
    2781
    时间
    1000ms
    内存
    128MiB
    难度
    5
    标签
    (无)
    递交数
    35
    已通过
    12
    上传者