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
这是暑假集训的一道题,题目大概意思就是有三个数列,在每一个数列里面找一个数,使得他们的和加起来的和要等于X,如果可以的话,输出yes,否则就输出no,
数列是五百的数量级,如果直接暴力枚举的话铁定会超时,一开始我使用便利前两个数列求和然后二分第三个数列,时间效率是N^2*logN,结果超时了。然后得到提示,
转变了一种思维方式,先遍历前两个数列求和,然后遍历第三个数列,对前两个数列的和进行二分查找,这样时间效率就变成了N^2+N*2*logN,就ac了


#include<iostream>
#include<algorithm>
using namespace std;
const int Max = 505*505;
const int sMax = 505;
int AllInt[Max] = { 0 };
int Aa[sMax]={0};
int Bb[sMax] = { 0 };
int Cc[sMax] = { 0 };
int sb = 1;


bool pan(int a,int b,int c,int d) {//二分过程,判断能不能组成X
 for (int i = 0; i < c; ++i) {
  int fir = 0, last = a*b - 1;
  int jb = d - Cc[i];
  while (fir <= last)
  {
   int mid = ((last - fir) >> 1) + fir;
   if (jb == AllInt[mid]) return true;
   else if (jb > AllInt[mid])
    fir = mid + 1;
   else if (jb < AllInt[mid]) last = mid-1;
  }
 }
 return false;
}

int* getAll(int a, int b) {//将前两个数列进行求和,然后对新生成的数组进行排序
 int k = 0;
 for (int i = 0; i < a; ++i)
 {
  for (int j = 0; j < b; ++j)
  {
   AllInt[k++] = Aa[i] + Bb[j];
  }
 }
 sort(AllInt, AllInt + a*b);
 return AllInt;
}



int main() {
 int A, B, C,D;
 while (cin >> A >> B >> C) {
  for (int i = 0; i < A; ++i)
  {
   cin >> Aa[i];
  }
  for (int i = 0; i < B; ++i)
  {
   cin >> Bb[i];
  }
  for (int i = 0; i < C; ++i)
  {
   cin >> Cc[i];
  }
  cin >> D;
  int dNum = 0;
  cout << "Case " << sb << ":" << endl;
  sb++;
  getAll(A, B);
  for (int i = 0; i < D; ++i)
  {
   cin >> dNum;
   if (pan( A, B, C, dNum)) cout << "YES" << endl;
   else cout << "NO" << endl;
  
  }
  memset(AllInt, 0, Max*sizeof(int));//每一组数据完后,清空数组
  memset(Aa, 0, sMax*sizeof(int));
  memset(Bb, 0, sMax*sizeof(int));
  memset(Cc, 0, sMax*sizeof(int));
 }
 system("pause>nul");
 return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值