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]++;
想知道为什么.....正着和反着倍增的区别这么大......