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;
}

浙公网安备 33010602011771号