其他分享
首页 > 其他分享> > 签到

签到

作者:互联网

原题链接

题目描述

背景:本来正在水群,计划12题,但是少了一题签到,群友给了建议(见样例下面的备注),就出了个签到题,在此感谢。

给定一个序列,你可以在序列中任取 44 个数 a,b,c,d (可以重复选取),问是否有一种选择满足:a+b+c=d。

输入描述:

第一行,一个正整数 n ( 1 <= n <= 1e3)
第二行 n 个整数 a1, a2, .... an (1 <= an <= 1e9)

输出描述:

如果存在一种情况满足,则输出"Yes"(不加引号),否则输出"No"(不加引号)。

样例

输入:
4
1 8 20 90

输出:
No

输入:
4
1 2 3 4

输出:
Yes

分析

暴力枚举三重 for 循环 + longn 的 二分查找, 必然会超时, 需要做的是, 将三重循环优化为两重
详情见代码

#include <iostream>
#include <algorithm>

using namespace std;

const int N = 1010, M = 1e6 + 10;

int n, t, a[N], sum[M];

//  二分查找, 是否存在 
bool find(int x)
{
	int l = 1, r = t;
	
	while(l < r)
	{
		int mid = l + r >> 1;
		
		if(sum[mid] >= x) r = mid;
		else l = mid + 1;
	}
	return sum[l] == x;
}

int main()
{
	cin >> n;
	for(int i = 1; i <= n; i ++) cin >> a[i];
	t = 1;
	
	sort(a + 1, a + n + 1);
	
	/*
	  要判断的等式为 a + b + c = d;
	  朴素写法的复杂度为 n^3*longn, 对于题目中的数据,必然超时
	  所以,先额外开一个数组 sum[],存放所有 a + b 的值 t 
	  等式就变为  d - c = t 然后再用 二分寻找 t 是否 存在
	*/
	 
	for(int i = 1; i <= n; i ++)
		for(int j = 1; j <= n; j ++)
			sum[t++] = a[i] + a[j];
	sort(sum + 1, sum + t);
	
	//  将三重 for 循环 优化为 两重 
	for(int i = n; i >= 1; i --)
	{
		for(int j = 1; j <= i; j ++)
		{
			int t = a[i] - a[j];
			if(find(t))
			{
				cout << "Yes" << endl;
				return 0;
			}
		}
	}
	
	cout << "No" << endl;
	
	return 0;
	
}

标签:二分,输出,签到,sum,mid,int,include
来源: https://www.cnblogs.com/ding-yu/p/16488291.html