深入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\n",i);return 0;} } return 0; }
陌上花开,可缓缓归矣,可斯人早已不在.