ACDream 1726 A Math game (折半查找)

A Math game

Time Limit: 2000/1000MS (Java/Others) Memory Limit: 256000/128000KB (Java/Others)

Submit Statistic Next Problem

Problem Description

Recently, Losanto find an interesting Math game. The rule is simple: Tell you a number H, and you can choose some numbers from a set {a[1],a[2],......,a[n]}.If the sum of the number you choose is H, then you win. Losanto just want to know whether he can win the game.

Input

There are several cases.
In each case, there are two numbers in the first line n (the size of the set) and H. The second line has n numbers {a[1],a[2],......,a[n]}.0<n<=40, 0<=H<10^9, 0<=a[i]<10^9,All the numbers are integers.

Output

If Losanto could win the game, output "Yes" in a line. Else output "No" in a line.

Sample Input

10 87
2 3 4 5 7 9 10 11 12 13
10 38
2 3 4 5 7 9 10 11 12 13

Sample Output

No
Yes

Manager

rihkddd

题意:给定n个数字,问能否使这些数字相加得到H?

分析:折半查找,先将前半部分的和算出来存在数组中,再将后半部分的数ans进行计算,然后在前半部分进行查找H-ans

这一题用到了一种新的写法,位运算。

用二进制来表示哪些数取了,哪些数没取。

比如,算前5个数字,2^5的二进制就是100000 那么可以把前面五个数的组合情况全部都表示出来

每一个二进制位表示第几个数,比如取第一和第三个数,那么二进制就是100101。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<stdlib.h>
#include<vector>
#include<queue>
#include<stack>
#include<algorithm>
#define LL long long
using namespace std;
const int MAXN=2e6+7;
int n,H;
int a[MAXN],sum[MAXN];
int main()
{
    int n,H;
    while(scanf("%d %d",&n,&H)!=EOF)
    {
        for(int i=0;i<n;i++)
            scanf("%d",&a[i]);
        int c=0,k=n>>1;
        for(int i=0;i<(1<<k);i++)
        {
            LL s=0;
            for(int j=0;j<k;j++)
            {
                if((1<<j)&i) s+= a[j];
            }
            if(s<=H) sum[c++]=s;
        }
        sort(sum,sum+c);
        int res=n-k;
        bool ok=false;
        for (int i=0;i<(1<<res);i++)
        {
            LL s=0;
            for(int j=0;j<res;j++)
            {
                if ((1<<j)&i) s+=a[k+j];
            }
            if (s>H) continue;
            if (sum[lower_bound(sum,sum+c,H-s)-sum]==H-s) {
                ok=true;
                break;
            }
        }
        puts(ok?"Yes":"No");
    }
    return 0;
}

时间: 2024-10-07 21:00:23

ACDream 1726 A Math game (折半查找)的相关文章

ACDREAM 1726 A Math game(折半枚举+hash)

题目链接: http://acdream.info/problem?pid=1726 题意: 给定n 个数,和一个数看,判断k能否由其中的任意个数的和组成. 分析: 因为n最大为40,暴力枚举所有的情况 复杂度为 2^40 肯定TLE ,然后就想到了折半枚举 分成两半,先处理前n/2个数的组合的情况 ,把所得结果哈希一下,然后再枚举后一半 的所有情况,然后在哈希表里查找.时间复杂度为 O(2^(N/2)); 代码如下: #include <stdio.h> #include <iostr

acdream 1726 A Math game (部分和问题 DFS剪枝)

A Math game Time Limit: 2000/1000MS (Java/Others) Memory Limit: 256000/128000KB (Java/Others) Problem Description Recently, Losanto find an interesting Math game. The rule is simple: Tell you a numberH, and you can choose some numbers from a set {a[1

ACdream 1726 A Math game (dfs+二分)

http://acdream.info/problem?pid=1726 官方题解:http://acdream.info/topic?tid=4246 求n个数里面能不能选一些数出来让它们的和等于k. 因为k很大,不能用背包,但是n很小,最大为40,所以拆成了2部分,之后最大为2^20次方<1050000;每次枚举前一半的和,然后用数组存储,然后得到一个总和减去后一半的差用二分查找. 1 #include<cstdio> 2 #include<cstring> 3 #inc

ACdream 1726 A Math game

深搜.不过有一个强大的剪枝.就是假设之后的全部用上都不能达到H,则return. if (A[n]-A[x-1]+summ< H) return; //A[n]表示前nx项和 #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn = 50; long long a[maxn], A[maxn]; int flag, n; long lon

快速排序和折半查找

package BinarySerach; import java.util.Scanner; public class BinarySerch { /** *折半查找和快速排序 */ static final int N = 15; static void quickSort(int [] array,int left,int right){ int f,t; int ltemp =left; int rtemp = right; //确定分界值 f = array[(left+right)/

C语言程序设计100例之(21):折半查找

例21  折半查找 问题描述 顺序查找是一种最简单和最基本的检索方法.其基本思想是:从检索表的一端(如表中第一个记录或最后一个记录)开始,逐个进行记录的关键字和给定值的比较.若某个记录的关键字和给定值比较相等,则查找成功:否则,若直至检索表的另一端(如最后一个记录或第一个记录),其关键字和给定值比较都不等,则表明表中没有待查记录,查找不成功. 顺序查找可以写成一个简单的一重循环,循环中依次将检索表(不妨设为数组a)中的元素与给定值比较,若相等,用break退出循环.算法描述为: for (i=0

查找之二折半查找(二分法查找)和插值查找

一.折半查找的前提是线性表中的记录必须好似关键码有序,线性表必须是顺序存储的. 二.折半查找 1 public class Binary_SearchDemo01 { 2 static int[] num = {0,1,3,5}; 3 public static void main(String[] args) { 4 int key = 3; 5 int x = Sequential_Search(key); 6 System.out.println(num[x]); 7 } 8 privat

查找之折半查找

1 #include<stdio.h> 2 #define N 10 3 4 void QuickSort(int a[],int left, int right); 5 int BinSearch(int a[], int low, int high, int key); 6 int main() 7 { 8 int a[N] = {2,8,4,9,7,6,5,3,1,0}; 9 int j = 0, i; 10 QuickSort(a, 0, sizeof(a)/sizeof(a[0])-

选择排序和冒泡排序以及折半查找

1.选择排序 2.冒泡排序 3.折半查找 方式一:开发使用的方法 方式二:普通的折半