ARC116B

考虑计算每对 \((a_i,a_j)\) 的贡献,即计算当 \(a_i\) 为最小值,\(a_j\) 为最大值时的方案数。将 \(a\) 排序后,显然 \((i,j)\) 中的元素可选可不选,\(i,j\) 必选,\([1,i)\)\((j,n]\) 必不选,共有 \(2^{j-i-1}\) 种方案(\(i=j\) 的情况另外计算)。不妨固定左端点 \(i\),考察贡献:

  • \(a_1 \times( a_2 + 2a_3 + \cdots + 2^{n-2}a_n)\)
  • \(a_2 \times( a_3 + 2a_4 + \cdots + 2^{n-3}a_n)\)
  • \(a_3 \times( a_4 + 2a_5 + \cdots + 2^{n-4}a_n)\)
  • \(\cdots\)

从后往前看,发现括号内的数是在下面一行乘 \(2\) 的基础上,再加上下面一行式子前面的数。于是就可以倒着扫一遍,求贡献即可。

时间复杂度 \(O(n\log n)\),瓶颈在排序。

#include <iostream>
#include <cstdio>
#include <algorithm>
#define int long long
#define N 1000001
#define MOD 998244353

using namespace std;

int n,a[N],sum,ans;

signed main()
{
    cin >> n;
    for( int i = 1 ; i <= n ; i ++ )
        cin >> a[i];
    sort( a + 1 , a + n + 1 );
    for( int i = n ; i >= 1 ; i -- )
    {
        ans = ( ans + a[i] * sum % MOD ) % MOD;
        ans = ( ans + a[i] * a[i] % MOD ) % MOD;//i=j 的情况
        sum = ( sum * 2 + a[i] ) % MOD;
    }
    cout << ans;
    return 0;
}
posted @ 2025-09-08 18:42  FormulaOne  阅读(14)  评论(0)    收藏  举报