CF101532C Large Summation(暴力模拟)

题面:

You are given an array a consisting of n element a1, a2, ..., an. For each element ai you must find another element aj (i ≠ j), such that the summation of ai and aj mod (109 + 7) (i.e. (ai + aj) % (109 + 7)) is as maximal as possible.

Can you help judges by solving this hard problem?

 

Input:

The first line contains an integer T, where T is the number of test cases.

The first line of each test contains an integer n (2 ≤ n ≤ 105), where n is the size of the array a.

The second line of each test case contains n integers a1, a2, ..., an (0 ≤ ai < 109 + 7), giving the array a.

 

Output:

For each test case, print a single line containing n space separated elements, such that the ith element is the answer to the ith element in the array a (i.e. the maximum value of (ai + aj) % (109 + 7)).

 

Example:

Input:

2
3
1 2 3
2
1000000000 1000000000

 

Output:

4 5 5
999999993 999999993

 

Note:

As input/output can reach huge size it is recommended to use fast input/output methods: for example, prefer to use scanf/printf instead of cin/cout in C++, prefer to use BufferedReader/PrintWriter instead of Scanner/System.out in Java.

 

分析:

给你一堆数,让你求出其中每个数和数组中另一个任意数两两相加可以得到的最大值,依次输出。

把数组升序排列,用二分法以刚好能和num[i]相加等于mod的那个数为界,把数组分为两部分,前部分的数和num[i]相加值小于等于mod,后部分与num[i]相加值处于mod~mod+num[i]间,因为num[i]的范围是不超过mod的,所以如果能找到与num[i]相加小于mod的数,其中最大的那个就是答案(因为后部分所得值%mod后,最大得到num[i]),否则答案就在后半段,且为末尾的那个数。

比较麻烦的是因为要进行排序,但是输出还是要按照最初的下标顺序来输出,我的话只能想到用两个数组分开操作,大佬的话使用了pair,用second来存初始下标。

虽然最好是能用上二分,不过看了大佬的代码发现直接顺序遍历来找也是不会TLE的。

自己虽然明白了原理但是写得抓耳挠腮,看了大佬代码真的感慨人和人的差距……

附大佬AC代码。

 

AC代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#define ll long long
using namespace std;
const int maxn = 100010;
const int mod = 1E9+7;
int t, n;
pair<ll, int>a[maxn];
ll ans[maxn];

void solve(){
	memset(ans, -1, sizeof(ans));
	sort(a+1, a+1+n);
	int j = n;
	for(int i = 1; i <= n; i++){
		for(; j >= 1; j--){
			if(i == j) continue;
			if(a[i].first + a[j].first >= mod) continue;
			ans[a[i].second] = a[i].first + a[j].first;
			break;
		}
		if(ans[a[i].second] == -1){
			ans[a[i].second] = (a[i].first + a[i == n ? n-1:n].first) %mod;
		}
	}
	for(int i = 1; i <= n; i++) cout<<ans[i]<<' ';
	cout<<endl;
}

int main(){
	
	cin>>t;
	while(t--){
		memset(ans, 0, sizeof(ans));
		cin>>n;
		for(int i = 1; i <= n; i++){
			ll mid;
			scanf("%lld", &mid);
			a[i] = make_pair(mid, i);
		}
		solve();
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值