【抽屉原理】D. Vupsen, Pupsen and 0

题目来源:Problem - D - Codeforceshttps://codeforces.com/contest/1582/problem/D

 

官方思路:

 解释:

对于数组元素个数进行 奇偶分析

当n为偶数时,我们将元素分成2/n对来处理,对于第一对 a1,a2;我们想让a1b1+a2b2为0,因此我们可以让b1=a2;b2=-a1;以此类推bi=ai+1;bi+1=-ai; 

这样能保证

 注意到 sum|bi|=sum|ai|<=maxN*maxA=10^4*10^5;

因此不会数值越界;

当n为奇数时,

我们先将末位3个元素与其他元素分开处理,这样就可以按照n为偶数时的处理方法先处理好前n-3个元素。对于an-2,an-1,an。根据迪利克雷原理(抽屉原理),三个数中一定有两个同正或同负的数之和不等于0(两个抽屉分别代表正数和负数,当有三个元素时,那一定有一个抽屉里有两个元素)。这样我们假设这三个数中的两个同号的数分别记为ai和aj,第三个数为ak,这样再令

bi=-ak;

bj=-ak;

bk=ai+aj;

于是有the sum of ai⋅bi+aj⋅bj+ak⋅bk=0;

再进行越界判断:

对于前n-3个元素,|b1|+|b2|+|b3|...+|bn-3|<=maxa*(maxn-1-3)

所以最后3个元素

bn−2+bn−1+bnbn−2+bn−1+bn <= MAXA+MAXA+2⋅MAXA=4⋅MAXAMAXA+MAXA+2⋅MAXA=4⋅MAXA, \

总和不会超过maxa*maxn=10^9

#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
#define pb push_back;
#define end  '\n';
void oper(vector<int>a, vector<int>b,int num)
{
	for (int i = 0; i < num; i+=2)
	{
		b[i] = -a[i + 1];
		b[i + 1] = a[i];
	}
	for (int i = 0;i < num; i ++)
	{
		cout << b[i] << ' ';
	}
}
void solve()
{
	int n;
	cin >> n;
	vector<int>a(n);
	vector<int>b(n);
	for(auto &x:a)
	{
		cin >> x;
	}
	if (n & 1)
	{
		oper(a, b, n - 3);
		int i, j, k;//抽屉原理,三种组合必有一个同正或同负
		if (a[n - 3] + a[n - 2])
		{
			k = a[n - 1];
			j = a[n - 2];
			i = a[n - 3];
			cout << -k << ' ' << -k << ' ' << i+j << end;
		}//在这里的区分上花了很多时间,希望能找到统一的规律
		else if (a[n - 3] + a[n - 1])
		{
			k = a[n - 2];
			j = a[n - 1];
			i = a[n - 3];
			cout << -k << ' ' << i + j << ' ' << -k << end;
		}		

		else
		{
			k = a[n - 3];
			j = a[n - 2];
			i = a[n - 1];
			cout << i + j << ' ' << -k << ' ' << -k << end;
		}
	}
	else
	{
		oper(a, b, n);
		cout << end;
	}
}
int main()
{
	std::ios::sync_with_stdio(0);
	std::cin.tie(0);
	int t;
	cin >> t;
	for (int TwT = 1; TwT <= t; ++TwT)
	{
		solve();
	}
}

猜你喜欢

转载自blog.csdn.net/nathanqian123/article/details/121015801
0