题解:AT_abc353_c [ABC353C] Sigma Problem

Idea

因为 ai<108a_i<10^8,所以 0<ai+aj<2×1080<a_i+a_j<2\times 10^8

考虑对于 ai+aj<108a_i+a_j<10^8ai+aj108a_i+a_j\ge 10^8 的情况分开讨论。

ai+aj<108a_i+a_j<10^8 时,这一组数对答案的贡献即为 ai+aja_i+a_j

反之,则贡献为 ai+aj108a_i+a_j-10^8

所以我们可以对 aa 序列从小到大排序,排序之后序列满足单调性。

可以对于每一个 ii,二分出一个 jj 使 ai+aj108a_i+a_j\ge10^8ai+aj1<108a_i+a_{j-1}<10^8。这一部分是 O(nlogn)\operatorname{O}(n\log n) 的。

因为有单调性,所以对于任意的 kk 使 kjk\ge jai+ak108a_i+a_k\ge 10^8

我们可以发现,最后对于每一个 ii,会减掉 nj+1n-j+110810^8

而设要减 cntcnt10810^8,则答案为:

i=1nj=1n(ai+aj)cnt×108\sum_{i=1}^{n}\sum_{j=1}^{n}(a_i+a_j)-cnt\times 10^8

如何求每一对 ai+aja_i+a_j 呢?考虑拆开:每一个 aia_i 会被加 n1n-1 次(与 n1n-1aja_j 相加) ,所以设 aa 数组总和为 sumsum,则每一对 ai+aja_i+a_j 的总和为 sum×(n1)sum\times(n-1)。这里是 O(n)\operatorname{O}(n) 的。

所以我们就能在 O(nlogn)\operatorname{O}(n\log n) 的时间复杂度内解决了。

Tip

  • 本题可能会爆 int

Code

#include<bits/stdc++.h>
using namespace std;
long long sum;
long long cnt=0;
int n,a[300005];
int main(){
	cin>>n;
	for(int i=1;i<=n;i++)cin>>a[i];
	sort(a+1,a+n+1);
	a[n+1]=100000000; 
	for(int i=1;i<=n;i++){
		int x=100000000-a[i];
		int _=lower_bound(a+i+1,a+n+2,x)-a;
	//	cout<<_<<' ';
		cnt+=(n-_+1);
		sum+=a[i];
	}
	sum=1ll*sum*(n-1);
	sum-=cnt*100000000;
	cout<<sum;
	return 0;
}
posted @   Weslie_qwq  阅读(2)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示