1. 程式人生 > 其它 >#雜湊,Pollard-Rho#JZOJ 6468 魚貫而入

#雜湊,Pollard-Rho#JZOJ 6468 魚貫而入

雜湊,Pollard-Rho

題目

\(n\)個數\(a_i\),現將其依次插入大小為\(len\)的雜湊表中,
問如何選擇\(n\)使得定址時間最大,求最大定址時間
\(n\leq 200,len\geq n,a_i\leq 10^{18}\)


分析

讓其定址時間最大就是讓它在模意義下重複次數儘量多,
重複當且僅當\(len|abs(a_i-a_j)\),作差是最難想的,
等於是讓len為\(abs(a_i-a_j)\)的約數即可,
那麼這樣的約數實際上有\(O(n^2\sqrt{A})\)
考慮如果\(len\)可行那麼,\(k*len\)不會更優,所以大於\(n^2\)的合數不會更優,
即只要判斷大於\(n^2\)的質數以及\([n,n^2]\)

內除以最小質因子小於\(n\)的數即可
這個定址的存放直接在原來的雜湊基礎上再開一個雜湊表,相當於是把\((x',x)\)裝進新的雜湊表中,
這樣就可以做到\(O(n^2A^{0.25}+n^3log_2A)\),但是比較卡常數,4s內勉強卡過


程式碼

#include <cstdio>
#include <cctype>
#include <cmath>
#include <algorithm>
#include <cstdlib>
#define rr register
using namespace std;
typedef long long lll; const int N=40009;
const double ha=pow(11.0,19/17.0); const int Prime[8]={2,61,97,7,13,17,23,29};
int prime[N],n,_h[N],ans,_n,m,v[N],Cnt,tot; lll o[N],h[N],B[N],b[N],a[N],H[N];
inline lll iut(){
	rr lll ans=0; rr char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
	return ans;
}
inline lll mo(lll a,lll b,lll mod){return a+b>=mod?a+b-mod:a+b;}
inline lll mul(lll a,lll b,lll mod){return (a*b-(lll)((long double)a/mod*b)*mod+mod)%mod;}
inline lll gcd(lll a,lll b){return b?gcd(b,a%b):a;}
inline lll ksm(lll x,lll y,lll mod){
	rr lll ans=1;
	for (;y;y>>=1,x=mul(x,x,mod))
	    if (y&1) ans=mul(ans,x,mod);
	return ans;
}
inline bool mr(lll n){
	if(n==46856248255981ll||n<2) return 0;
    if(n==2||n==3||n==7||n==61||n==24251) return 1;
    if (!(n&1)||!(n%3)||!(n%7)||!(n%61)||!(n%24251)) return 0;
    rr lll m=n-1; rr int cnt=0;
    while (!(m&1)) m>>=1,++cnt;
	for (rr int i=0;i<5&&Prime[i]<n;++i){
		rr lll now=ksm(Prime[i],m,n),ls=now;
		for (rr int j=1;j<=cnt;++j){
			now=mul(now,now,n);
			if (now==1&&ls!=1&&ls!=n-1) return 0;
			ls=now;
		}
		if (now!=1) return 0;
	} 
	return 1;
}
inline lll rho(lll n,lll h){
	if (!(n&1)) return 2;
	if (!(n%3)) return 3;
	rr lll x1=(rand()+1)%n,x2=x1,p=1;
	for (rr int k=2;;k<<=1,x2=x1,p=1){
		for (rr int i=1;i<=k;++i){
			x1=mo(mul(x1,x1,n),h,n);
			p=mul(p,x1>x2?x1-x2:x2-x1,n);
			if (!(i&127)){
				rr lll d=gcd(p,n);
				if (d>1) return d;
			}
		}
		rr lll d=gcd(p,n);
		if (d>1) return d;
	}
}
inline void dfs(lll n){
	if (n==1) return;
	if (mr(n)){
		B[++B[0]]=n;
		return;
	}
	rr lll t=n;
	while (t==n) t=rho(n,rand()%(n-1)+1);
	while (!(n%t)) n/=t;
	dfs(t),dfs(n);
}
inline signed locate(lll x){
	rr int j=x%N;
	while (h[j]!=-1&&h[j]!=x) j=(j+1)%N;
	return j;
}
inline void answ(lll mod){
	rr int sum=0; _h[0]=0;
	for (rr int i=1;i<=n;++i){
		for (rr lll j=o[i]%mod;;j=(j+1)%mod,++sum){
			rr int t=locate(j);
			if (h[t]==-1){
				H[t]=o[i],h[t]=j,
				_h[++_h[0]]=t;
				break;
			}
			if (H[t]==o[i]) break;
		}
	}
	for (rr int i=1;i<=_h[0];++i)
	    h[_h[i]]=H[_h[i]]=-1;
	if (ans<sum) ans=sum;
}
signed main(){
	freopen("hash.in","r",stdin);
	freopen("hash.out","w",stdout);
	iut(),n=iut(),srand(N);
	for (rr int i=0;i<N;++i) h[i]=-1;
	for (rr int i=1;i<=n;++i) o[i]=a[i]=iut();
	sort(a+1,a+1+n),m=unique(a+1,a+1+n)-a-1,_n=n*n,v[1]=1;
	for (rr int i=2;i<=_n;++i){
		if (!v[i]) v[i]=prime[++Cnt]=i;
		for (rr int j=1;j<=Cnt&&prime[j]*i<=_n;++j){
			v[i*prime[j]]=prime[j];
			if (i%prime[j]==0) break;
		}
	}
	for (rr int i=1;i<m;++i)
	for (rr int j=i+1;j<=m;++j)
	{
		B[0]=0,dfs(a[j]-a[i]);
		for (rr int k=1;k<=B[0];++k)
		    if (B[k]>n*n) b[++tot]=B[k];
	}
	sort(b+1,b+1+tot),tot=unique(b+1,b+1+tot)-b-1;
	for (rr int i=1;i<=tot;++i) answ(b[i]);
	for (rr int i=n;i<=_n;++i) if (i/v[i]<n) answ(i);
	return !printf("%d",ans);
}