深入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=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
const long long maxn=3000027;
long long x[maxn],y[maxn];
const long long mod=1000007;
long long a,b,c,a1,b1,c1;
long long n,ans=0;
long long lin[maxn],ver[maxn],nex[maxn],ver1[maxn],len=0;
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*100007%mod+y*1007%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[1]=read();a=read();b=read();c=read();
    y[1]=read();a1=read();b1=read();c1=read();
    find(x[1],y[1]);
    for(long long i=2;;++i)
    {
        x[i]=(x[i-1]*a+b+i-1)%c;
        y[i]=(y[i-1]*a1+b1+i-1)%c1;
        find(x[i],y[i]);
        if(ans==n){printf("%lld
",i);return 0;}
    }
    return 0;
}
View Code

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

原文地址:https://www.cnblogs.com/chdy/p/10050368.html