poj3349
#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;
int ad[100000][6],hd[100003],n,el,flag;
struct S
{
int p[6];
bool operator < (const S &a)const
{
int i;
for(i=0;i<6;i++)
{
if(p[i]<a.p[i])return 1;
else if(p[i]>a.p[i])return 0;
}
return 1;
}
}s[12];
struct E
{
int v,p;
}e[100000];
inline void adde(int u,int v)
{
e[el].v=v,e[el].p=hd[u],hd[u]=el++;
}
void adjust(int n)
{
int i,j,min=0;
for(i=0;i<6;i++)
{
for(j=0;j<6;j++)
{
s[i].p[j]=ad[n][(i+j)%6];
}
}
for(i=0;i<6;i++)
{
for(j=0;j<6;j++)
{
s[i+6].p[j]=ad[n][(i-j+6)%6];
}
}
for(i=0;i<12;i++)
if(s[i]<s[min])min=i;
for(i=0;i<6;i++)
ad[n][i]=s[min].p[i];
}
inline bool same(int x,int y)
{
int i;
for(i=0;i<6;i++)
if(ad[x][i]!=ad[y][i])
return 0;
return 1;
}
inline void hash(int n)
{
int i=0,j,k;
for(j=0;j<6;j++)
{
i+=ad[n][j]*(j+1),i%=100003;
}
for(k=hd[i];k!=-1;k=e[k].p)
{
if(same(k,n)) flag=1;
}
adde(i,n);
}
int main()
{
int i,j,k;
while(~scanf("%d",&n))
{
memset(hd,-1,sizeof(hd));
el=0,flag=0;
for(i=0;i<n;i++)
{
for(j=0;j<6;j++)
scanf("%d",&ad[i][j]),ad[i][j]%=100003;
if(!flag)
{
adjust(i);
hash(i);
}
}
if(flag)printf("Twin snowflakes found.\n");
else printf("No two snowflakes are alike.\n");
}
return 0;
}
一开始使用的hash函数为平方和,但是始终会出现tle,经过多次试验把hash函数改为现在的样子后ac,看之前的代码:
void hash(int n)
{
int i=0,j,k;
for(j=0;j<6;j++)
{
i+=(ad[n][j]+j)*(ad[n][j]+j),i%=100003;
}
for(k=hd[i];k!=-1;k=e[k].p)
{
if(same(k,n)) flag=1;
}
adde(i,n);
}
对比ac之后的代码,开始的时候认为是两倍的访存时间导致了TLE,后来又实验了:
inline void hash(int n)
{
int i=0,j,k;
for(j=0;j<6;j++)
{
k=ad[n][j]+j;
i+=k*k,i%=100003;
}
for(k=hd[i];k!=-1;k=e[k].p)
{
if(same(k,n)) flag=1;
}
adde(i,n);
}
仍然TLE,我就回想到了gcc的优化问题 在之前一次的貌似两倍访存会被优化为一次访存,但是计算部分仍然是乘法运算,因为要计算平方的数可能很大,而后的代码中的乘法是乘以一个常量的,
在gcc优化的时候会使用LEA指令来进行乘法运算,时间会节省很多。
浙公网安备 33010602011771号