4 Values whose Sum is 0 POJ - 2785 & Can you find it? HDU - 2141(二分)

本文介绍了一种解决四数求和问题的有效算法,通过将原始问题转化为查找两个数之和的有效实现,使用二分查找技术优化查找过程。该算法适用于竞赛编程及实际问题求解。

4 Values whose Sum is 0
Time Limit: 15000MS Memory Limit: 228000K
Total Submissions: 26489 Accepted: 7976
Case Time Limit: 5000MS

Description

The SUM problem can be formulated as follows: given four lists A, B, C, D of integer values, compute how many quadruplet (a, b, c, d ) ∈ A x B x C x D are such that a + b + c + d = 0 . In the following, we assume that all lists have the same size n .

Input

The first line of the input file contains the size of the lists n (this value can be as large as 4000). We then have n lines containing four integer values (with absolute value as large as 2 28 ) that belong respectively to A, B, C and D .

Output

For each input file, your program has to write the number quadruplets whose sum is zero.

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

Sample Explanation: Indeed, the sum of the five following quadruplets is zero: (-45, -27, 42, 30), (26, 30, -10, -46), (-32, 22, 56, -46),(-32, 30, -75, 77), (-32, -54, 56, 30).

Source

[Submit]   [Go Back]   [Status]   [Discuss]

题意:给你四列数,问从这四列数中各选一个数使他们的和是0的情况有多少种?

思路:二分找答案,先将前两列数分别加起来存到一个新的数组sum里,然后再遍历后两列的数的和,看从sum数组中是否能找到他们的相反数,如果有就让ans+1;

//直接利用二分函数
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<algorithm>
#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<stack>
#define inf 0x3fffffff
using namespace std;
typedef long long LL;
const double eps=1e-8;
const double pi=acos(-1);
const int N=4e3+1;
int n,a[N],b[N],c[N],d[N],s[N*N],tot;
int finf(int x)
{
    int l=lower_bound(s,s+tot,x)-s;
    int r=upper_bound(s,s+tot,x)-s;
    return r-l;
}
int main()
{
    tot=0;
    int ans=0;
    scanf("%d",&n);
    for(int i=0;i<n;i++)
        scanf("%d%d%d%d",&a[i],&b[i],&c[i],&d[i]);
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
            s[tot++]=a[i]+b[j];
    sort(s,s+tot);
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
            ans+=finf(-(c[i]+d[j]));
    printf("%d\n",ans);
}
 
//自己写二分查找
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<algorithm>
#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<stack>
#define inf 0x3fffffff
using namespace std;
typedef long long LL;
const double eps=1e-8;
const double pi=acos(-1);
const int N=4e3+1;
int n,a[N],b[N],c[N],d[N],s[N*N],tot;
int finf(int x)
{
    int ansl,ansr,mid;
    int l=0,r=tot;
    while(l<r)
    {
        mid=(l+r)/2;
        if(s[mid]>=x) r=mid;
        else l=mid+1;
    }
    ansl=l;
    l=0,r=tot;
    while(l<r)
    {
        mid=(l+r)/2;
        if(s[mid]>x) r=mid;
        else l=mid+1;
    }
    ansr=l;
    return ansr-ansl;
}
int main()
{
    tot=0;
    int ans=0;
    scanf("%d",&n);
    for(int i=0;i<n;i++)
        scanf("%d%d%d%d",&a[i],&b[i],&c[i],&d[i]);
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
            s[tot++]=a[i]+b[j];
    sort(s,s+tot);
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
            ans+=finf(-(c[i]+d[j]));
    printf("%d\n",ans);
}



 
那我们再接着来看一道一模一样的题: 

Can you find it?

Time Limit: 10000/3000 MS (Java/Others)    Memory Limit: 32768/10000 K (Java/Others)Total Submission(s): 37412    Accepted Submission(s): 9145
Problem Description
Give you three sequences of numbers A, B, C, then we give you a number X. Now you need to calculate if you can find the three numbers Ai, Bj, Ck, which satisfy the formula Ai+Bj+Ck = X.
 
Input
There are many cases. Every data case is described as followed: In the first line there are three integers L, N, M, in the second line there are L integers represent the sequence A, in the third line there are N integers represent the sequences B, in the forth line there are M integers represent the sequence C. In the fifth line there is an integer S represents there are S integers X to be calculated. 1<=L, N, M<=500, 1<=S<=1000. all the integers are 32-integers.
 
Output
For each case, firstly you have to print the case number as the form "Case d:", then for the S queries, you calculate if the formula can be satisfied or not. If satisfied, you print "YES", otherwise print "NO".
 
Sample Input
 
 
3 3 31 2 31 2 31 2 331410
 

Sample Output
 
 
Case 1:NOYESNO
 
Author
wangye
 
Source
 
Recommend
威士忌
 题意:给你三列数,然后n次查询,每次给出一个数,问是否能从那三列数中各选出一个使得他们的和等于这个数,如果能输出YES,否则NO。心路历程:是不是很简单啊,确实很简单啊,不是跟上面的一模一样的吗?这两道题分别出现在这三天的两场比赛中,中间只隔了一天,看到这题的时候内心很是激动,因为上一场刚刚出现过所以印象还是非常清晰的,代码也很快就写出来了,但是一交MLE????这种情况没遇到过几次,当时有点懵,然后算了一下空间复杂度,好像确实超了(我的新的sum数组里存的是三个数列的各种情况的和,要开n*n*n大小的数组,n<=500,题目内存只给了10000 kB,确实会超),然后我同样用map存三个数列的各种情况 的和还是MLE,当时认真想了一下,既然存三个数列的和的情况会MLE,那就存先两个数列的各种情况和呗,但我依旧用的是map来操作,so 结果依旧是MLE,这个时候就有点绝望了,这都不行,算了一下空间感觉够啊(不知道map里面的空间会占多少?),比赛的时候就是没有再用二分试一下存两个数列的各种情况的和,比赛刚结束我问旁边的伙伴,他说用二分存前两列的各种情况和我就恍然大悟,,,,,,,,,啊,又一次和AC擦肩而过,多么好的AC机会啊,多么痛的领悟啊!!!!!!!!!!!!以后比赛如果遇到这种情况,一定要把所有想到情况都是一遍,不要怕wa,不要怕罚时,反正已经罚时爆炸了,怕什么微笑微笑
接下来就直接看代码吧:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<algorithm>
#include<iostream>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<vector>
#define inf 0x3fffffff
using namespace std;
typedef long long LL;
const double eps=1e-8;
const double pi=acos(-1);
const int N=502;
int aa,bb,cc,tot;
LL a[N],b[N],c[N],sum[N*N];
int main()
{
    int s,d,t=1,ans,flag;
    while(~scanf("%d%d%d",&aa,&bb,&cc))
    {
        tot=flag=0;
        for(int i=0;i<aa;i++)
            scanf("%I64d",&a[i]);
        for(int i=0;i<bb;i++)
            scanf("%I64d",&b[i]);
        for(int i=0;i<cc;i++)
            scanf("%I64d",&c[i]);
        for(int i=0;i<aa;i++)
            for(int j=0;j<bb;j++)
                sum[tot++]=a[i]+b[j];
        sort(sum,sum+tot);
        scanf("%d",&s);
        printf("Case %d:\n",t++);
        while(s--)
        {
            scanf("%d",&d);
            flag=0;
            for(int i=0;i<cc;i++)
            {
                ans=lower_bound(sum,sum+tot,d-c[i])-sum;
                if(sum[ans]==d-c[i])
                {
                    flag=1;
                    printf("YES\n");
                    break;
                }
            }
            if(!flag) printf("NO\n");
        }
    }
}



先看效果: https://renmaiwang.cn/s/jkhfz Hue系列产品将具备高度的个性化定制能力,并且借助内置红、蓝、绿三原色LED的灯泡,能够混合生成1600万种不同色彩的灯光。 整个操作流程完全由安装于iPhone上的应用程序进行管理。 这一创新举措为智能照明控制领域带来了新的启示,国内相关领域的从业者也积极投身于相关研究。 鉴于Hue产品采用WiFi无线连接方式,而国内WiFi网络尚未全面覆盖,本研究选择应用更为普及的蓝牙技术,通过手机蓝牙与单片机进行数据交互,进而产生可调节占空比的PWM信号,以此来控制LED驱动电路,实现LED的调光功能以及DIY调色方案。 本文重点阐述了一种基于手机蓝牙通信的LED灯设计方案,该方案受到飞利浦Hue智能灯泡的启发,但考虑到国内WiFi网络的覆盖限制,故而选用更为通用的蓝牙技术。 以下为相关技术细节的详尽介绍:1. **智能照明控制系统**:智能照明控制系统允许用户借助手机应用程序实现远程控制照明设备,提供个性化的调光及色彩调整功能。 飞利浦Hue作为行业领先者,通过红、蓝、绿三原色LED的混合,能够呈现1600万种颜色,实现了全面的定制化体验。 2. **蓝牙通信技术**:蓝牙技术是一种低成本、短距离的无线传输方案,工作于2.4GHz ISM频段,具备即插即用和强抗干扰能力。 蓝牙协议栈由硬件层和软件层构成,提供通用访问Profile、服务发现应用Profile以及串口Profiles等丰富功能,确保不同设备间的良好互操作性。 3. **脉冲宽度调制调光**:脉冲宽度调制(PWM)是一种高效能的调光方式,通过调节脉冲宽度来控制LED的亮度。 当PWM频率超过200Hz时,人眼无法察觉明显的闪烁现象。 占空比指的...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值