hdu5183 hash大法

维护前缀和sum[i]=a[0]-a[1]+a[2]-a[3]+…+(-1)^i*a[i]
枚举结尾i,然后在hash表中查询是否存在sum[i]-K的值。
如果当前i为奇数,则将sum[i]插入到hash表中。
上面考虑的是从i为偶数为开头的情况。
然后再考虑以奇数开头的情况,按照上述方法再做一次即可。
不同的是这次要维护的前缀和是sum[i]=-(a[0]-a[1]+a[2]-a[3]+…+(-1)^i*a[i])
I为偶数的时候将sum[i]插入到hash表。
总复杂度o(n)

注意一个tips:scanf读long long的时候别忘了%I64d,否则会出错

------注意几个黑科技orz-------

1.这题丧心病狂到了卡常数的程度= =,所以hash的时候用map肯定是不行的。。。。

借助了kuangbin原创的hash模板orz

const int HASH = 1000007;
struct HASHMAP
{
    int head[HASH],next[MAXN],size;
    long long state[MAXN];
    void init()
    {
        size = 0;
        memset(head,-1,sizeof(head));
    }
    bool check(long long val){
        int h = (val%HASH+HASH)%HASH;
        for(int i = head[h];i != -1;i = next[i])
            if(val == state[i])
                return true;
        return false;
    }
    int insert(long long val)
    {
        int h = (val%HASH+HASH)%HASH;
        for(int i = head[h]; i != -1;i = next[i])
            if(val == state[i])
            {
                return 1;
            }
        state[size] = val;
        next[size] = head[h];
        head[h] = size++;
        return 0;
    }
} H1,H2;

init:初始化  insert:插入  check:查找是否存在

2.Huge Data,还需要读入优化:

基本思想就是把输入数据以一个一个字符的形式读入

template <class T>
inline bool scan_d(T &ret) {
   char c; int sgn;
   if(c=getchar(),c==EOF) return 0; //EOF
   while(c!=‘-‘&&(c<‘0‘||c>‘9‘)) c=getchar();
   sgn=(c==‘-‘)?-1:1;
   ret=(c==‘-‘)?0:(c-‘0‘);
   while(c=getchar(),c>=‘0‘&&c<=‘9‘) ret=ret*10+(c-‘0‘);
   ret*=sgn;
   return 1;
}

使用方法:scan_d(a[i]);

  1 #include <cstdio>
  2 #include <cstring>
  3 using namespace std;
  4 #define MAXN 1000010
  5 #define LL   long long
  6 int a[MAXN];
  7 LL S1,S2;
  8 LL k;
  9 int n,TC;
 10
 11 const int HASH = 1000007;
 12 struct HASHMAP
 13 {
 14     int head[HASH],next[MAXN],size;
 15     long long state[MAXN];
 16     void init()
 17     {
 18         size = 0;
 19         memset(head,-1,sizeof(head));
 20     }
 21     bool check(long long val){
 22         int h = (val%HASH+HASH)%HASH;
 23         for(int i = head[h];i != -1;i = next[i])
 24             if(val == state[i])
 25                 return true;
 26         return false;
 27     }
 28     int insert(long long val)
 29     {
 30         int h = (val%HASH+HASH)%HASH;
 31         for(int i = head[h]; i != -1;i = next[i])
 32             if(val == state[i])
 33             {
 34                 return 1;
 35             }
 36         state[size] = val;
 37         next[size] = head[h];
 38         head[h] = size++;
 39         return 0;
 40     }
 41 } H1,H2;
 42
 43
 44 template <class T>
 45 inline bool scan_d(T &ret) {
 46    char c; int sgn;
 47    if(c=getchar(),c==EOF) return 0; //EOF
 48    while(c!=‘-‘&&(c<‘0‘||c>‘9‘)) c=getchar();
 49    sgn=(c==‘-‘)?-1:1;
 50    ret=(c==‘-‘)?0:(c-‘0‘);
 51    while(c=getchar(),c>=‘0‘&&c<=‘9‘) ret=ret*10+(c-‘0‘);
 52    ret*=sgn;
 53    return 1;
 54 }
 55
 56
 57 int main()
 58 {
 59     //freopen("in.txt","r",stdin);
 60     scanf("%d",&TC);
 61     for (int TT=1;TT<=TC;TT++)
 62     {
 63         scanf("%d%I64d",&n,&k);
 64         for (int i=0;i<n;i++)
 65             scan_d(a[i]);
 66             //scanf("%d",&a[i]);
 67
 68         bool ans=false;
 69         H1.init();
 70         H2.init();
 71         H1.insert(0);
 72         //H2.insert(0);
 73         S1=a[0];    S2=-a[0];
 74         if (H1.check(S1-k))   ans=true;
 75         if (H2.check(S2-k))   ans=true;
 76         H2.insert(S2);
 77
 78         for (int i=1;i<n;i++)
 79         {
 80             if (i%2==0)
 81             {
 82                 S1=S1+a[i];
 83                 S2=S2-a[i];
 84                 H2.insert(S2);
 85             }
 86             else
 87             {
 88                 S2=S2+a[i];
 89                 S1=S1-a[i];
 90                 H1.insert(S1);
 91             }
 92             if (H1.check(S1-k))
 93                 ans=true;
 94             if (H2.check(S2-k))
 95                 ans=true;
 96             if (ans)    break;
 97         }
 98
 99         printf("Case #%d: ",TT);
100         if (ans)    printf("Yes.\n");   else printf("No.\n");
101     }
102     return 0;
103 }

HASH大法有时候真的蛮重要的orz

时间: 2024-10-11 21:22:38

hdu5183 hash大法的相关文章

NOIP 2014 D2T3 解方程 Hash大法好

题目大意:给定高次方程an*x^n+...+a1*x^1+a0*x^0=0 求[1,m]区间内有多少个整数根 ai<=10^10000,m<=100W 懒得高精,考场上写的long double乱搞--30分打底50分顶天QAQ 当我终于搞定了各种非官方数据之后,我只能长跪大地,手捧鲜花,仰望上苍高喊:哈希大法好! 首先阿贝尔在200年前告诉我们 五次以上方程没有求根公式 于是我们只能枚举1~m 这个是100W 然后100W再加上1W位的精度 都不用运算直接就是跪-- 怎么办呢QAQ 哈希大法

Vijos P1915 解方程 加强版 还是Hash大法好!

题目大意:同解方程 数据范围m<=10^8 O(m)做法见 http://blog.csdn.net/popoqqq/article/details/40984859 O(m)跪了你就当我没辙么? 首先找到一个比较靠谱的第一个质数 将对第一个质数取模为0的值全都存在一个数组里 由于这个是有循环节的 所以我们只需要处理出[0,p-1]中对第一个质数取模为0的数就可以搞出所有了 然后对于这个数组里的所有数用剩余的质数验证一遍就行了 时间复杂度未知 但是第一个质数必须靠谱 如果第一个质数被卡掉那就退化

UVA 11107 - Life Forms(Hash+LCP)

UVA 11107 - Life Forms 题目链接 题意:给定一个字符串,找出重复出现超过m次的字串的最大开始下标 思路:hash大法,需要点人品,然后二分答案,每次利用hash值去找出最大下标即可 代码: #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef unsigned long long ull; const ull x = 123; c

UVA 261 - The Window Property(字符串Hash)

UVA 261 - The Window Property 题目链接 题意:这题题意挺绕的..就是给定一个字符串长度n,扫描长度为k = [1,n],然后每次只能扫描连续k个字符的子串,要求所有扫描中,每次扫描中出现的不同字符串个数都不超过k + 1,那么这个字符串就是window property,如果不是的话,就还要找出下标最小的不符合的位置(就是n次扫描中找最小的) 思路:Hash大法好,长度才100,直接处理出hash,O(n^2)随便搞掉 代码: #include <cstdio>

NOIP2017SummerTraining0705 T1 重复字符串

题目描述 给定两个字符串a和b,我们可以定义一些操作:a*b为将字符串a和字符串b连接起来,比如a= "aoe",b= "jkw",那么a*b= "aoejkw".进一步,我们可以有指数操作,a^0="", a^1=a, a^2=a*a, a^n=a*(a^(n-1))=a*a*-*a (n个a) 现在给你一个字符串,你可以将它看成是a^n的形式,比如字符串"abababab",可以认为是"aba

BZOJ3555 [Ctsc2014]企鹅QQ 题解

题目大意: 有一些字符串,求其中两个等长且恰好只有一位不同的字符串的对数. 思路: Hash大法好!正着倒着各来一遍(底数不同),之后枚举不同的那一位,前后两段拼起来之后为了有区分前面一部分再乘一个数.模数用unsigned long long自然溢出. 代码: 1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 using namespace std; 5 const int S1=1007,

【Tyvj 1060】【NOIP 2005】等价表达式

设a为一个质数,模数为另一个质数,然后暴力算多项式的答案,如果答案相等就认为两个多项式相等. 这种hash有出错概率的题为什么还是要用hash呢?因为出错的概率实在太小了,a和模数的值取得好出题人根本没法卡. 然后贡献了2次WA,第一次因为判断数字时没判断边界,第二次因为乘法运算时爆int了!!! hash大法好- #include<cstdio> #include<cstring> #include<algorithm> using namespace std; ty

【ZZNU-oj-2116:人间不值得】(1亿以内的货币拼音转数值求折扣价原价)--hash+String大法好+字符串处理+超大暴力模拟题

B : 人间不值得 概览问题列表状态排名编辑 Progress Bar 时间限制:1 Sec 内存限制:256 MiB提交:146 答案正确:12 提交 编辑 题目描述 家缠万贯来几时,我今停杯一问之.人攀暴富不可得,贫穷却与人相随.何以解忧,唯有暴富.spring做梦都想暴富,但是又苦于囊中羞涩.每次消费都会精打细算,所以每次消费都会记在小本本上.可惜spring是个汉字盲,你能帮他来完成汉字拼音转化为数字么.spring每次的消费都是一行格式表示分别为原价(或折扣价) 价格   折扣度  

BZOJ3578 GTY的人类基因组计划2 HASH

题意:有N个人M个房间,初始时所有人都在1号房间,维护:1.让某个人去某个房间  2.假如[l,r]中所有的人还未一起统计过,Ans+=人数.输出Ans 题解: 集合HASH get 根据异或的性质,a^x^x=a,因此一个集合的HASH值就是其所有元素的异或起来的值 接下来就是STL大法好 将每个房间看成一个集合,每个人赋一个初始rand,set存储当前所有HASH值没有出现过的房间.对于每个询问,二分出所有区间之间的房间,统计答案即可. #include <set> #include &l