ACdreamOJ 1726 hash

http://acdream.info/problem?pid=1726

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
/**
ACdreamOJ  1726 hash
题目大意:给定n个数,问这些数的部分和是否可以组成m
解题思路:由于n的最大值只有40,因此我们把所有的数分成均等的两部分,利用哈希查寻一下就可以了
*/
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
#include <queue>
#include <map>
using namespace std;
typedef long long LL;
const int MAXN=1<<20;
const int HASH = 1000007;

struct hashmap//建立哈希表
{
    LL a[MAXN];
    int head[HASH],next[MAXN],size;
    void init() //初始化
    {
        memset(head,-1,sizeof(head));
        size=0;
    }
    bool find(LL val) //查找一个元素是否在哈希表内
    {
        int tmp = (val%HASH + HASH)%HASH;
        for(int i = head[tmp]; i!=-1; i=next[i])
            if(val==a[i]) return true;
        return false;
    }
    void add(LL val) //添加元素到哈希表中
    {
        int tmp =(val%HASH+HASH)%HASH;
        if(find(val)) return;
        a[size]=val;
        next[size]=head[tmp];
        head[tmp]=size++;
    }
} h1;
int n,m,num[55];
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        h1.init();
        for(int i=0; i<n; i++)
        {
            scanf("%d",&num[i]);
        }
        int t=n/2;
        for(int i=0; i<(1<<t); i++)
        {
            LL sum=0;
            for(int j=0; j<t; j++)
            {
                if(i&(1<<j))
                {
                    sum+=num[j];
                }
            }
            if(sum>m)continue;
            h1.add(sum);
        }
        int tt=n-t;
        int flag=0;
        for(int i=0; i<(1<<tt); i++)
        {
            LL sum=0;
            for(int j=0; j<tt; j++)
            {
                if(i&(1<<j))
                {
                    sum+=num[t+j];
                }
            }
            if(sum>m)continue;
            if(h1.find(m-sum))
            {
                flag=1;
                break;
            }
        }
        if(flag)
            printf("Yes\n");
        else
            printf("No\n");
    }
    return 0;
}
时间: 2024-10-07 02:35:31

ACdreamOJ 1726 hash的相关文章

ACdreamOJ 1116 斐波那契数列+hash计算后缀

http://acdream.info/problem?pid=1116 Problem Description give you a string, please output the result of the following function mod 1000000007 n is the length of the string f() is the function of fibonacci, f(0) = 0, f(1) = 1... a[i] is the total numb

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

ACdreamoj 1011(树状数组维护字符串hash前缀和)

题目链接:http://acdream.info/problem? pid=1019 题意:两种操作,第一种将字符串某个位置的字符换为还有一个字符.另外一种查询某个连续子序列是否是回文串: 解法:有两种hash的办法,所以写了两种解法;首先hash是x1 * p^1+ x2*p^2 +x3*p^3...能够用树状数组维护前缀和,维护两个串,一个是正串.还有一个是反串用于比較.比較时候乘以对应的p倍数推断是否相等. 刘汝佳白书上的hash方法处理这道题更复杂:改动i会对后缀j产生的影响为a*p^(

AC dreamoj 1011 树状数组+hash维护字符串的前缀和

http://acdream.info/problem?pid=1019 Problem Description Now we have a long long string, and we will have two kinds of operation on it. C i y : change the ith letter to y. Q i j : check whether the substring from ith letter to jth letter is a palindr

一致性hash算法 - consistent hashing

1.背景 我们都知道memcached服务器是不提供分布式功能的,memcached的分布式完全是由客户端来实现的.在部署memcached服务器集群时,我们需要把缓存请求尽可能分散到不同的缓存服务器中,这样可以使得所有的缓存空间都得到利用,而且可以降低单独一台缓存服务器的压力.     最简单的一种实现是,缓存请求时通过计算key的哈希值,取模后映射到不同的memcahed服务器.这种简单的实现在不考虑集群机器动态变化的情况下也是比较有效的一种方案,但是,在分布式集群系统中,简单取模的哈希算法

BZOJ3198 SDOI2013 spring HASH+容斥原理

题意:给定6个长度为n的数列,求有多少个数对(i,j)((i,j)≡(j,i))使得i和j位置恰好有K个数相同,其中0≤K≤6 题解: 设fi=至少有K个数相同的位置对的数量,用2^6枚举每一种可能,根据容斥原理,答案就是\[\sum\limits_{i = K}^N {{f_i}C_i^K{{\left( { - 1} \right)}^{i - K}}} \] 至于多乘一个组合数,是因为当前枚举到有x个数相同,一个位置对有i个相同的数,那么累计的时候就会算成$C_x^i$,因此实际上这个位置

hash算法搜索获得api函数地址的实现

我们一般要获得一个函数的地址,通常采用的是明文,例如定义一个api函数字符串"MessageBoxA",然后在GetProcAddress函数中一个字节一个字节进行比较.这样弊端很多,例如如果我们定义一个杀毒软件比较敏感的api函数字符串,那么可能就会增加杀毒软件对我们的程序的判定值,而且定义这些字符串还有一个弊端是占用的字节数较大.我们想想如何我们的api函数字符串通过算法将它定义成一个4字节的值,然后在GetProcAddress中把AddressOfNames表中的每个地址指向的

BZOJ_3207_花神的嘲讽计划1_(Hash+主席树)

描述 http://www.lydsy.com/JudgeOnline/problem.php?id=3207 给出一个长度为\(n\)的串,以及\(m\)个长度为\(k\)的串,求每个长度为\(k\)的串在原串\([x,y]\)区间是否出现过. 分析 这道题要求对比长度为\(k\)的串,于是我们把这些串的Hash值都算出来,问题就转化成了求\([x,y]\)的区间中是否出现过某Hash值. 求区间中某一个值出现了多少次,可以用主席树. p.s. 1.学习了主席树指针的写法,比数组慢好多啊...

Hash算法专题

1.[HDU 3068]最长回文 题意:求一个字符串(len<=110000)的最长回文串 解题思路:一般解法是manacher,但是这一题用hash也是可以ac的 假设当前判断的是以i为中心偶数最长回文串,那么s[2*i+1-k……i]与s[i+1……k]的哈希值必定相同 假设当前判断的是以i为中心奇数最长回文串,那么s[2*i-k……i-1]与s[i+1……k]的哈希值必定相同 用二分求出相应的k 1 #include <iostream> 2 #include <algori