关于哈希
查看原帖
关于哈希
97582
星夜之使楼主2021/1/15 10:36

rt,如果像下面这样写第一个点和第二个点就会哈希冲突。

#include<bits/stdc++.h>
#define IT map<unsigned long long,long long>::iterator 

using namespace std;

int n,m,k,high;
unsigned long long val[40][501][501],mi[40];

int wx[8]={1,0,-1,0,1,1,-1,-1},wy[8]={0,1,0,-1,1,-1,1,-1};

long long gcd(long long x,long long y)
{
	if(!y) return x;
	else return gcd(y,x%y);
}

map<unsigned long long,long long> check;

long long ansx=0,ansy=0;

int main()
{
	ios::sync_with_stdio(0);

	cin>>n>>m>>k;
	
	high=log2(k)+1;
	
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			char x;
			cin>>x;
			val[0][i][j]=x;
		}
	}
	
	mi[0]=51061ull;
	
	for(int i=1;i<=30;i++)
	{
		mi[i]=mi[i-1]*mi[i-1];
	}
	
	for(int dir=0;dir^8;dir++)
	{
		for(int len=1;len<=high;len++)
		{
			for(int i=1;i<=n;i++)
			{
				for(int j=1;j<=m;j++)
				{
					int plx,ply;
					
					plx=(i+wx[dir]*(1<<(len-1))%n+n)%n;
					if(plx==0) plx=n;
					
					ply=(j+wy[dir]*(1<<(len-1))%m+m)%m;
					if(ply==0) ply=m;
				
					val[len][i][j]=val[len-1][i][j]*mi[len]+val[len-1][plx][ply];
				}
			}	
		}
		
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=m;j++)
			{
				int tmp=k,tmp2=0,plx=i,ply=j;
				unsigned long long hsh=1283ull;
				
				while(tmp)
				{
					if(tmp&1)
					{
						hsh*=mi[tmp2];
						hsh+=val[tmp2][plx][ply];
						
						plx+=wx[dir]*(1<<(tmp2));
						plx=(plx%n+n)%n;
						
						if(plx==0) plx=n;
						
						ply+=wy[dir]*(1<<(tmp2));
						ply=(ply%m+m)%m;
						
						if(ply==0) ply=m;
					}
					
					tmp>>=1;
					tmp2++;
				}
				
				check[hsh]++;
			}
		}
	}
	
	ansy=(long long)n*n*m*m*8*8;
	
	for(IT i=check.begin();i!=check.end();i++)
	{
		ansx+=i->second*i->second;
	}
	
	long long tmp=gcd(ansx,ansy);
	
	cout<<ansx/tmp<<"/"<<ansy/tmp<<'\n';
	
	return 0;
}

但是这样就不会(76行开始)

for(int len=high;len>=0;len--)
				{
					tmp2=len;
				
					if(tmp&(1<<len))
					{
						tmp-=(1<<len);
					
						hsh*=mi[tmp2];
						hsh+=val[tmp2][plx][ply];
						
						plx+=wx[dir]*(1<<(tmp2));
						plx=(plx%n+n)%n;
						
						if(plx==0) plx=n;
						
						ply+=wy[dir]*(1<<(tmp2));
						ply=(ply%m+m)%m;
						
						if(ply==0) ply=m;
					}
					
				//	tmp>>=1;
				//	tmp2++;
				}
				
				check[hsh]++;

想知道为什么.....正着和反着倍增的区别这么大......

2021/1/15 10:36
加载中...