您的位置:首页 > 理论基础 > 数据结构算法

POJ 1840 Eqs

2012-08-22 16:35 309 查看
唉,我的入门“hash”

题目链接:http://poj.org/problem?id=1840

CSUST2012年暑假8月组队后第十二次个人赛:http://acm.hust.edu.cn:8080/judge/contest/view.action?cid=11900#problem/B

Eqs

TimeLimit: 5000MS MemoryLimit: 65536K
TotalSubmissions: 8973 Accepted: 4446
Description

Considerequationshavingthefollowingform: 

a1x13+a2x23+a3x33+a4x43+a5x53=0 

Thecoefficientsaregivenintegersfromtheinterval[-50,50]. 

Itisconsiderasolutionasystem(x1,x2,x3,x4,x5)thatverifiestheequation,xi∈[-50,50],xi!=0,anyi∈{1,2,3,4,5}. 

Determinehowmanysolutionssatisfythegivenequation. 

Input

Theonlylineofinputcontainsthe5coefficientsa1,a2,a3,a4,a5,separatedbyblanks.
Output

Theoutputwillcontainonthefirstlinethenumberofthesolutionsforthegivenequation.
SampleInput
3729414347

SampleOutput
654

Source
RomaniaOI2002

题目大意:给你一个方程a1x13+
a2x23+a3x33+
a4x43+a5x53=0
,输入a1,a2,a3,a4,a5.它们的范围都在[-50,50]
       问在区间xi∈[-50,50],
xi!=0一共有多少个解,满足这个方程。


相关算法:hash

至于什么是hash本菜鸟自己也只清楚一点点,实在不好解释,大家还是自己去找一本算法书看去吧推荐严蔚敏的(C语言版)《数据结构》
要看清华大学出版社出版的,中国电力出版社的不是很清楚。下面我就在这道题目中插入一些本人对hash的理解。(我看的是一本比较旧的书在251页)

hash的关键是建立传说中的hash散表,搞的这么神秘说白了就是一个数组而已,hash的好处就是快速查找,以某种形式将要查的结果对应于你建立的hash数组的下标,具体的转化方法自己问度娘,确立这种对应关系要尽量避免冲突,或者有一个很好的方法来避免冲突,一般的hash表都有冲突的情况,当然本题目例外,(PS:什么叫冲突比如说你要查找a和b,而根据你确立的hash表,a和b都是存入了下标为c的数组了,那么当你看到c时,你到底要用的是a还是b呢,这就是传说中的冲突,上学期弄了好久也没搞明白这个问题TOT)。

本题目的hash数组的确立:
我的思路是把方程的一部分以下标的形式存入hash数组中。
关键:如何转化,hash数组的范围是多少。
注意:数组的下标不能为负数。
首先转化方程:a1x13+
a2x23+a3x33+
a4x43+a5x53=0
转化为 a1x13+a2x23=
-(a3x33+a4x43+
a5x53  )
 
             容易知道 的范围肯定比 的范围小,而二者又要相等,所以以前者的范围来确立hash数组的大小。
 
             我们知道方程中各个因子的范围都是[-50,50],所以|a*x^3|<=50^4=6250000,因为有正有负,而且方程被分割成了两部分,而数组的下 
      
         标又必须是非负数,所以hash数组的大小是2*2*50^4=2500
0000.才能完全不冲突。
注意:因为这个数组开到了两千五百万,所以很容易超内存,从而hash数组定义为char型,开始一直用int,改了好久啊!!!
代码分析:
//Accepted	24656KB	469ms	C++	859B	2012-08-2209:34:05
#include<stdio.h>
#include<string.h>
constintmaxn=25000000;//50^4*2*2
charhash[maxn];//注意定义为char类型,否则会超内存
intmain()
{
inta1,a2,a3,a4,a5;
inti,j,k;
intsum,temp;
while(scanf("%d%d%d%d%d",&a1,&a2,&a3,&a4,&a5)!=EOF)
{
sum=0;
memset(hash,0,sizeof(hash));//开始全部初始化为0
for(i=-50;i<=50;i++)
{
for(j=-50;j<=50;j++)
{
if(i!=0&&j!=0)
{
temp=a1*i*i*i+a2*j*j*j;//从头开始枚举,把每一个结果都存入下标中,注意可能会有很多种情况temp一样,所以是hash[]++
hash[temp+maxn/2]++;//加上maxn/2保证数组下标为正数,
}
}
}
for(i=-50;i<=50;i++)
for(j=-50;j<=50;j++)
for(k=-50;k<=50;k++)
if(i!=0&&j!=0&&k!=0)
{
temp=a3*i*i*i+a4*j*j*j+a5*k*k*k;
if(temp>=-maxn/2&&temp<=maxn/2)//注意判断范围,第二个范围较大,如果不判断,会溢出
{
sum+=hash[-temp+maxn/2];//因为前面已经枚举了所有的情况,所以后面加上没一个hash的下标所对应的值就行了,反正如果没有这种情况,下标对应的值也是0对结果没有影响。。。
}
}
printf("%d\n",sum);
}
return0;
}




 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息