O - Can you find it?(二分法)

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 3 1 2 3 1 2 3 1 2 3 3 1 4 10

Sample Output

Case 1: NO YES NO

题目大意及分析

给定三个数组a,b,c,每个数组有若干个数(<=500个),再给定一个数s要你判断是否存在s=a[i]+b[j]+c[k],存在一组数就输出YES,一组都不存在就输出NO。

因为只有三个500大小的数组,刚开始我直接写了三个for循环,超时,再看看题目就更清楚了,每组测试数据中给的s是<=1000个,这就很容易超时,而且,给的数可以是负数,这样我sort全部排序,也无济于事。

无奈之下直接百度,才发现已经AC的人都先把a数组和b数组中的数相加成一个ab[500×500]的数组,这样就相当于ab[i]+c[j]=s;再变形一下,ab[i]=c[j]+s;这样我就知道接下来要干什么了,只要在ab数组里用以前学的二分查找看能否把c[j]+s找出来,貌似以前也有过这类要把数据关系进行转换的题。

代码如下:

#include<cstdio>
#include<cstdlib>
int a[501],b[501],c[501],d[260000];int k,n,m;
int cmp(const void*a,const void*b)
{
     return *(int*)a-*(int*)b;
}
int main(void)
{
     int t,s,mm=1;
     while(scanf("%d%d%d",&k,&n,&m)!=EOF)
     {
for(int i=0;i<k;i++) scanf("%d",&a[i]);
         for(int i=0;i<n;i++) scanf("%d",&b[i]);
         for(int i=0;i<m;i++) scanf("%d",&c[i]);
         int cnt=0;
         for(int i=0;i<n;i++)
             for(int j=0;j<m;j++)
                d[cnt++]=b[i]+c[j];
         qsort(a,k,sizeof(a[0]),cmp);
         qsort(d,cnt,sizeof(d[0]),cmp);
         scanf("%d",&t);
         printf("Case %d:\n",mm++);
         while(t--)
          {
            int flag=0;
             scanf("%d",&s);
             for(int i=0;i<k;i++)
               {
                 int tl=0,tr=cnt-1;
                 int tt=s-a[i];
                 while(tl<tr)
                {
                     int mid=(tl+tr)/2;
                     if(d[tl]==tt || d[tr]==tt || d[mid]==tt){flag=1;break;}
                     else if(d[mid]<tt)tl=mid+1;
                     else tr=mid-1;
                 }
                 if(flag==1) break;
             }
             if(flag==1) puts("YES");
             else if(flag==0) puts("NO");
          }
     }
     return 0;
}

时间: 2024-08-28 20:00:49

O - Can you find it?(二分法)的相关文章

day05匿名函数,内置函数,二分法,递归,模块

yield作为表达式来使用的方式 #grep -rl 'python /root """ 查找root下文件中含有python的文件 """ import os def init(func): def wrapper(*args,**kwargs): g=func(*args,**kwargs) next(g) return g return wrapper @init def search(target): while True: search

Python写个二分法查找

笔者是一个通信测试攻城狮,之前做过一段时间的持续集成.工作内容只要就是对主线版本进行基本通信功能守护,测试执行都是自动化完成,也是那个时候开始接触到代码. 当时经常遇到的一个问题是:某一天我们发现版本有重大BUG,但是到上一次我们验证PASS中间已经经历过很多版本,我们需要手动从中间找到第一个出现BUG的版本,当然最简单的方法是二分法,取中间版本,根据有没有BUG再缩小范围,继续取中间版本...当时我的想法就是思路很固定,完全可以自动化完成,可惜当时我不会写代码...直到今天看Python递归函

函数嵌套 ,名称空间与作用域 ,闭包函数 ,装饰器 ,迭代器, 生成器 三元表达式,列表解析,生成器表达式 递归与二分法, 内置函数

函数嵌套名称空间与作用域闭包函数装饰器迭代器生成器三元表达式,列表解析,生成器表达式递归与二分法内置函数--------------------------------------------函数的嵌套调用:在调用一个函数的过程中,又调用了其他函数函数的嵌套定义:在一个函数的内部,又定义另外一个函数def max(x,y): if x>y: return x else: return ydef max1(a,b,c,d): res=max(a,b) res2=max(res,c) res3=ma

二分法练习1

在房神的激励下我开始预习二分法啦~ poj3273 Monthly Expense (二分,最大值最小化) 题意:将N个账款分割成M个财务期,使得每个分期账款和的最大值最小. 题解:贪心思想,二分法.上界为N天花费总和,下界为每天花费的最大值.根据mid值遍历n天花费看是否满足M各财务期条件 1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 int main(){ 5 int n,m,i,cnt,a[

LeetCode 1 Two Sum(二分法)

题目来源:https://leetcode.com/problems/two-sum/ Given an array of integers, find two numbers such that they add up to a specific target number. The function twoSum should return indices of the two numbers such that they add up to the target, where index1

03-1. 二分法求多项式单根

二分法求函数根的原理为:如果连续函数f(x)在区间[a, b]的两个端点取值异号,即f(a)f(b)<0,则它在这个区间内至少存在1个根r,即f(r)=0. 二分法的步骤为: 检查区间长度,如果小于给定阈值,则停止,输出区间中点(a+b)/2:否则 如果f(a)f(b)<0,则计算中点的值f((a+b)/2): 如果f((a+b)/2)正好为0,则(a+b)/2就是要求的根:否则 如果f((a+b)/2)与f(a)同号,则说明根在区间[(a+b)/2, b],令a=(a+b)/2,重复循环:

二分法排序

算法思想简单描述: 在插入第i个元素时,对前面的0-i-1元素进行折半,先跟他们 中间的那个元素比, 如果小,则对前半再进行折半,否则对后半 进行折半,直到left>right, 然后再把第i个元素前1位与目标位置之间 的所有元素后移,再把第i个元素放在目标位置上. 二分法排序最重要的一个步骤就是查找要插入元素的位置, 也就是要在哪一个位置上放我们要准备排序的这个元素. 当我们查找到位置以后就很好说了,和插入排序一样, 将这个位置以后的所有元素都向后移动一位.这样就实现了二分法排序. 然后是怎么

4thweek.P_problemB .poj1505copy books.二分法

题目大意: 有m本书,k个抄写员.m本书的页码分别为 p1,p2……pm…….他们同时开始抄写且工作效率相同.要求分配给抄写员们若干书,每个抄写员要抄写的书的顺序必须是连续相邻的. 请你分配书使他们在最少的时间里完成抄写任务. 分析: 使每个抄写员分配到的页数的最大值尽可能小.最大值的最小化问题加二分法应用. 输入输出案例: Sample Input 2 9 3 100 200 300 400 500 600 700 800 900 5 4 100 100 100 100 100 Sample

二分法

namespace 二分法 { class Program { static void Main(string[] args) { //二分法前提:数组必须是有序的. int[] a = new int[] { 3, 4, 6, 8, 9, 10, 13, 16 }; Console.WriteLine("请输入你想要找的数:"); int find = Convert.ToInt32(Console.ReadLine()); int top, bottom, mid; //定义上限下

黄金分割二分法数值分析回顾

今天看了2012年写的对黄金分割二分法的数值探讨,推理公式不记得了,当时写的不细致,晚上回顾了下,做了些补充 原文: http://blog.csdn.net/aaajj/article/details/7878480 比如ABCDE 5个节点,通过以下斐波拉契数列二分方式组织起来, 找A需要3次,即从5开始到A的路径 找B需要3次 找C需要2次 找D需要2次 找E需要2次 平均期望次数E=总次数 / 节点数 = (3+3+2+2+2) / 5 = 2.4 这里,设斐波拉契数列Tn 为 1 1