POJ1840 Eqs(哈希)
地址链接http://poj.org/problem?id=1840
a1x13+ a2x23+ a3x33+ a4x43+ a5x53=0等价于 a1x13+ a2x23+ a3x33=a4x43+ a5x33
所以使用哈希储存前三项的值,而数组开到101^3=1030301就够了
有几个需要注意的地方就是x不能等于0(应为这个我纠结了好久,所以看题啊啊~~);
然后就是求解的个数,所以在用哈希存前三个数的和时,就不能完全(直接将其替代),那样将会丢掉一种解,所以我的方法就是直接在sum数组中存101^3个数,在搜索的时候一条哈希值相等的链就要搜到尾,找出共有多少个(其实也可以用个数组记录到目前为止这个数出现的个数,将会减少一部分搜索的时间,但是我的也就用了900+Ms,所以也就没改了);
另外一个需要注意的地方就是和可以是负数,所以取余时就要先反号。
另外,我突然发现,把MAXN改为1000007比这个代码还要快100多Ms,而且Memory也小了很多,由此可见写一个好的哈希函数是很重要的~~~
当我把1000007改为100007时,时间居然只有500+Ms,真是出乎意料,所以说哈希也有相当大的一部分运气成分,有时提交超时也许只要改一下哈希函数就可以Ac也讲不好,实在无语。。。。
代码如下:
1 #include<cstdio> 2 #include<cstring> 3 #define mem(a) memset(a,0,sizeof(a)) 4 #define MAXN 2000007 5 #define maxn 1030302 6 #define lf(a) a*a*a 7 int hash[MAXN+5],next[maxn+5]; 8 int sum[maxn+5],index; 9 void insert(int num)//插入一个数num 10 { 11 int numm=num>0?num:-num; 12 int h=(numm%MAXN+numm/MAXN)%MAXN;//哈希函数 13 sum[index]=num; 14 next[index]=hash[h]; 15 hash[h]=index++; 16 } 17 int is_find(int num) 18 { 19 int number=0; 20 int numm=num>0?num:-num; 21 int h=(numm%MAXN+numm/MAXN)%MAXN; 22 int u=hash[h]; 23 while(u){ //一条链要搜到尾,找到这个值的可行数 24 if(sum[u]==num)number++; 25 u=next[u]; 26 } 27 return number;//返回可行数 28 } 29 int main() 30 { 31 int a[5]; 32 while(~scanf("%d%d%d%d%d",&a[0],&a[1],&a[2],&a[3],&a[4])) 33 { 34 mem(sum);index=1; 35 mem(hash);mem(next); 36 int i,j,k,count=0; 37 for(i=-50;i<=50;i++)if(i!=0) 38 for(j=-50;j<=50;j++)if(j!=0) 39 for(k=-50;k<=50;k++)if(k!=0) 40 insert(a[0]*lf(i)+a[1]*lf(j)+a[2]*lf(k)); 41 42 for(i=-50;i<=50;i++)if(i!=0) 43 for(j=-50;j<=50;j++)if(j!=0) 44 count+=is_find((-a[3])*lf(i)-a[4]*lf(j)); 45 printf("%d\n",count); 46 } 47 return 0; 48 }