#2020.01.14训练题解#二分入门(B题)

题源HDU-2578

HDU-2578-Dating with girls(1)

Description
Everyone in the HDU knows that the number of boys is larger than the number of girls. But now, every boy wants to date with pretty girls. The girls like to date with the boys with higher IQ. In order to test the boys ’ IQ, The girls make a problem, and the boys who can solve the problem
correctly and cost less time can date with them.
The problem is that : give you n positive integers and an integer k. You need to calculate how many different solutions the equation x + y = k has . x and y must be among the given n integers. Two solutions are different if x0 != x1 or y0 != y1.
Now smart Acmers, solving the problem as soon as possible. So you can dating with pretty girls. How wonderful!

Input
The first line contain an integer T. Then T cases followed. Each case begins with two integers n(2 <= n <= 100000) , k(0 <= k < 2^31). And then the next line contain n integers.

Output
For each cases,output the numbers of solutions to the equation.

Sample Input
2
5 4
1 2 3 4 5
8 8
1 4 5 7 8 9 2 6

Sample Output
3
5

题意

  • 输入T代表有T组测试数据,每组测试数据输出n和k,代表有n个待选数,和要求的x+y=k中的k
  • 对于每组测试数据,输出有多少种不同的解法,x和y必须在n个待选数中

题解

  • 这是一道整数二分的题,对所给的n个待选数需要进行sort排序,然后对下标进行二分
  • 因为这次要求的x和y必须在所给数之间
  • 对于x,在所给数之间遍历,然后对于每一个x二分找y
  • left==right的时候推出了循环,同时,对于当前的x,y只剩一种可能
  • 虽然现在的y不一定满足x+y=k,但下面几行代码进行判断满足方程再计数即可
  • 注意输入可能重复,需要进行去重
  • 遍历得到x时,如果这次的x等于前一次的x,那么若满足方程,sum计数后还得还原
  • 即发现满足方程先计数;再判断是否重复重复sum自减

涉及知识点

  • 二分 算法(此题属于整数二分)
  • 对于二分的算法-详见链接博客介绍二分

AC代码

#include
#include
using namespace std;
int n;
int main()
{
	int T;
	long long k,ans[100010];
	scanf("%d",&T);
	while(T--)
	{
		int sum=0,right=0;
		scanf("%d %lld",&n,&k);
		for(int i=0;i<n;i++)
		{
			scanf("%lld",&ans[i]);
		}
		sort(ans,ans+n);//升序 
		int mid,left;
		for(int i=0;i<n;i++)
		{
			left=0;
			right=n-1;
			while(left<right)
			{
				mid=(left+right)/2;
				if(ans[i]+ans[mid]<k) left=mid+1;
				else if(ans[i]+ans[mid]>k) right=mid-1;
				else
				{
					left=mid;
					break;
				}
			}
			if(ans[i]+ans[left]==k)//去重 
			{
				sum++;
				if(i!=0&&ans[i]==ans[i-1]) sum--;
				/*
					||和&&有逻辑短路功能,A&&B中,如果A是假的B就不会再被计算
					即可防止ans[I-1]可能导致的下标越界
					同理,A||B中,如果A是真的B就不会再被计算咯
				*/
			}
		}
		printf("%d\n",sum);
	}
	return 0;
}

你可能感兴趣的:(2020.01.14训练题解)