专栏文章
【[ABC151E] Max-Min Sums】题解
AT_abc151_e题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @mip5w86y
- 此快照首次捕获于
- 2025/12/03 06:40 3 个月前
- 此快照最后确认于
- 2025/12/03 06:40 3 个月前
思路
我们不可能暴力枚举所有子集,所以考虑每个元素对答案的贡献。
注意到,在一个子集中,只有头尾两个元素对答案有贡献。当一个元素为子集中最大值时,对答案有一个正的贡献;当为最小值时,有一个负的贡献。
因此,只需要对于每个元素,求出其作为最大和最小值的次数就可以了。
因此,只需要对于每个元素,求出其作为最大和最小值的次数就可以了。
我们先考虑最大值的情况,最小值同理。
显然,对于一个元素,其为子集中最大值,当且仅当其余元素都不大于该元素。
考虑排序,将大小关系转化为先后顺序。则对于一个下标 ,其作为最大值的子集为前 个元素中选出 个再加上它本身,即该元素的正贡献为 。
考虑排序,将大小关系转化为先后顺序。则对于一个下标 ,其作为最大值的子集为前 个元素中选出 个再加上它本身,即该元素的正贡献为 。
同理,负贡献为 ,总贡献为 。
而计算组合数,对于能看到这里的选手来说,一定是 trivial 的。
显然有:
预处理乘法逆元即可。
AC Code
CPP#include <bits/stdc++.h>
#define UP(i, l, r) for(int i = (l); i <= (r); ++ i)
#define DN(i, l, r) for(int i = (r); i >= (l); -- i)
#define LUP(i, l, r) for(ll i = (l); i <= (r); ++ i)
#define LDN(i, l, r) for(ll i = (r); i >= (l); -- i)
#define FE(i, s) for(auto i : s)
#define PB push_back
using namespace std;
using ll = long long;
using ull = unsigned long long;
using pii = pair<int, int>;
using vi = vector<int>;
const int INF = 0x3f3f3f3f, INFB = 0x3f, N = 1e5, MOD = 1e9 + 7;
const ll INFLL = 0x3f3f3f3f3f3f3f3f;
int n, k, a[N + 5];
ll fac[N + 5], ifc[N + 5], ans;
ll qpow(ll a, ll b){
ll res = 1ll;
for(; b; b >>= 1){
if(b & 1) res = res * a % MOD;
a = a * a % MOD;
}
return res;
}
ll md(ll x){ return (x % MOD + MOD) % MOD; }
ll c(ll n, ll m){ return n >= m ? (fac[n] * ifc[m] % MOD) * ifc[n - m] % MOD : 0; }
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> n >> k;
fac[0] = 1;
UP(i, 1, n){
cin >> a[i];
fac[i] = fac[i - 1] * i % MOD;
}
ifc[n] = qpow(fac[n], MOD - 2);
DN(i, 0, n - 1) ifc[i] = ifc[i + 1] * (i + 1) % MOD;
sort(a + 1, a + n + 1);
UP(i, 1, n) ans = md(ans + md(md(c(i - 1, k - 1) - c(n - i, k - 1))) * a[i]);
cout << ans;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...