Week4 B - 四个数列

Week4 B - 四个数列
ZJM 有四个数列 A,B,C,D,每个数列都有 n 个数字。ZJM 从每个数列中各取出一个数,他想知道有多少种方案使得 4 个数的和为 0。

当一个数列中有多个相同的数字的时候,把它们当做不同的数对待。

请你帮帮他吧!

Input
第一行:n(代表数列中数字的个数) (1≤n≤4000)

接下来的 n 行中,第 i 行有四个数字,分别表示数列 A,B,C,D 中的第 i 个数字(数字不超过 2 的 28 次方)

Output
输出不同组合的个数。

Sample Input

6
-45 22 42 -16
-41 -27 56 30
-36 53 -37 77
-36 30 -75 -46
26 -38 -10 62
-32 -54 -6 45

Sample Output

5

Hint
样例解释: (-45, -27, 42, 30), (26, 30, -10, -46), (-32, 22, 56, -46),(-32, 30, -75, 77), (-32, -54, 56, 30).

解题思路
暴力就TL
要用点特别的 二分
先将前两组相加 并用 sort 排序
再将后两个数组相加的相反数丢进特制的查找函数中
函数里用两个二分分别找出最先出现的位置 ans1 和最后出现的位置 ans2
若没找到返回 -1 若找到将 ans2 - ans1 + 1 返回
将这些正值相加就是符合题目的次数

Code

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string>
#include<algorithm>
using namespace std;

int t=0;
int s[4][40000];
long long ss[2][16000000];
bool cmp(int a,int b){
	return a<b;
}

int findf(int x){
	int f=0;int e=t-1;
	int ans1=-1;
	int ans2=-1;
	while(f<=e){
		if(ss[0][(f+e)/2]==x){
			ans1=(f+e)/2;
			e=(f+e)/2-1;
		}else if(ss[0][(f+e)/2]>x){
			e=(f+e)/2-1;
		}else if(ss[0][(f+e)/2]<x){
			f=(f+e)/2+1;
		}
	}
	f=0;e=t-1;
	while(f<=e){
		if(ss[0][(f+e)/2]==x){
			ans2=(f+e)/2;
			f=(f+e)/2+1;
		}else if(ss[0][(f+e)/2]>x){
			e=(f+e)/2-1;
		}else if(ss[0][(f+e)/2]<x){
			f=(f+e)/2+1;
		}
	}
	if(ans1!=-1)return ans2-ans1+1;
	return 0;
}



int main(){
	int n;
	cin>>n;
	for(int i=0;i<n;i++){
		cin>>s[0][i]>>s[1][i]>>s[2][i]>>s[3][i];
	}
	int ans=0;
	t=0;
	for(int i=0;i<n;i++){
		for(int y=0;y<n;y++){
			ss[0][t]=s[0][i]+s[1][y];
			t++;
		}
	}
	sort(ss[0],ss[0]+t);
	
	for(int i=0;i<n;i++){
		for(int y=0;y<n;y++){
			ss[1][t]=s[2][i]+s[3][y];
			ans+=findf(-1*(s[2][i]+s[3][y]));
		}
	}
	
	cout<<ans<<endl;
	
}
发布了17 篇原创文章 · 获赞 0 · 访问量 208

猜你喜欢

转载自blog.csdn.net/qq_43324189/article/details/104980490
今日推荐