深入hash

  hash真的很好用,这些杂一点的知识点我觉得还是很有必要的,对还有离散化。

深入hash

1<=N<=1,000,000,其它所有数据都在[0...1,000,000,000]范围内

看起来很简单一道水题,其实也不是很容易,认真思考会发现这道题是道hash,产生点并产生n个不同的点就行了嘛,直接hash一下不就好了,套入公式,输出28,怎么回事?调,再调,终于发现公式带错了,i->i-1才对因为我是直接枚举的i。

调出来了,提交,发现50超时的很厉害,发现为什么呢,这不就是道简单的hash么,然后经过思考是hash数字的地址重复的太多了尽管用了吊链法,但是重复的太多在查找当前链的时候消耗很多的时间,这时考虑优化,(⊙v⊙)。

那就把mod改一下,再修改一下key,使key不容易重复。终于过了,深入理解了hash,还需找一些比较不容易重复的地址才行!

#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<iomanip>
#include<cmath>
#include<ctime>
#include<vector>
#include<stack>
#include<queue>
#include<map>
#include<algorithm>
using namespace std;
inline long long read()
{
long long x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
const long long maxn=;
long long x[maxn],y[maxn];
const long long mod=;
long long a,b,c,a1,b1,c1;
long long n,ans=;
long long lin[maxn],ver[maxn],nex[maxn],ver1[maxn],len=;
void add(long long x,long long y,long long u)
{
ver[++len]=y;
ver1[len]=u;
nex[len]=lin[x];
lin[x]=len;
}
void find(long long x,long long y)
{
long long key=(x*%mod+y*%mod)%mod;
for(long long i=lin[key];i;i=nex[i])
if(ver[i]==x&&ver1[i]==y)return;
add(key,x,y);++ans;
return;
}
int main()
{
//freopen("1.in","r",stdin);
n=read();
x[]=read();a=read();b=read();c=read();
y[]=read();a1=read();b1=read();c1=read();
find(x[],y[]);
for(long long i=;;++i)
{
x[i]=(x[i-]*a+b+i-)%c;
y[i]=(y[i-]*a1+b1+i-)%c1;
find(x[i],y[i]);
if(ans==n){printf("%lld\n",i);return ;}
}
return ;
}

陌上花开,可缓缓归矣,可斯人早已不在.

上一篇:go标准库的学习-regexp


下一篇:maven项目中的pom.xml