ABC353C Sigma Problem 题解
ABC353C Sigma Problem 题解
题目链接:AT
题目中的两个求和符号 实际上是在枚举所有的有序数对 。而有序数对的个数 ,真的去枚举所有数对肯定会 T。这时应该考虑去拆贡献,求出每个 对答案的贡献。
这道题的一个要点是要注意到题目中 。也就是说,对于任意的 ,要么 ,此时有 ;要么 ,此时有 。
现在暂时不考虑第二种情况。这时所求的答案实际上就是枚举所有有序数对 ,求和 。因为每个 恰好出现在 个数对中,所以此时的答案是 。
(为什么每个 恰好出现在 个数对中?原因十分简单:因为我们枚举了所有的有序数对,所以每个 一定和除了它本身之外的所有 个元素都“配对”过一次,因此就出现在 个数对中。当然,因为是有序数对,可能 有时是数对的第一个元素,有时是数对的第二个元素,但这显然不影响答案。)
如果考虑第二种情况,最终的答案就要减去若干个 。具体减去多少个呢?对于某个 ,找出所有满足 且 的 的个数,那么 就对答案贡献了这么多个 。(这里限定 是因为题目中要求有序数对,不这么限定会导致重复计算。)于是可以先把 数组排序,对于某个 ,就可以二分查找出第一个满足 且 的 ,于是满足条件的 的总数就是 。
(为什么排序不会改变答案?要点在于题目中的 函数满足“交换律”,或者说 ,所以可以随意调换数组元素的顺序而不改变答案。与之区分的是本场比赛的 D 题,那道题和本题很像,都是枚举所有的有序数对 ,然后求值某个二元函数的函数值的和。但 D 题的函数不满足这种“交换律”,所以不能先排序再求和。)
综上,我们先求出所有 的和的 倍,再枚举所有的 ,找出应该减去多少个 即可。时间复杂度 ,瓶颈在排序和二分查找。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
constexpr int MAXN = 3e5 + 10;
constexpr ll MOD = 1e8;
int n;
ll a[MAXN], ans, cnt;
int main()
{
cin >> n;
for(int i = 1; i <= n; i++) cin >> a[i], ans += (n-1) * a[i];
sort(a + 1, a + n + 1);
for(int i = 1; i < n; i++)
{
ll x = MOD - a[i];
int pos = lower_bound(a + i + 1, a + n + 1, x) - a; // 注意这里是从 a[i+1] 开始找的,这样能确保不会重复计算
cnt += n - pos + 1;
}
ans -= cnt * MOD;
cout << ans << endl;
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】