唉,我的入门“hash”
题目链接:http://poj.org/problem?id=1840
CSUST 2012年暑假8月组队后第十二次个人赛:http://acm.hust.edu.cn:8080/judge/contest/view.action?cid=11900#problem/B
Eqs
Time Limit: 5000MS | Memory Limit: 65536K | |
Total Submissions: 8973 | Accepted: 4446 |
Description
Consider equations having the following form:
a1x13+ a2x23+ a3x33+ a4x43+ a5x53=0
The coefficients are given integers from the interval [-50,50].
It is consider a solution a system (x1, x2, x3, x4, x5) that verifies the equation, xi∈[-50,50], xi != 0, any i∈{1,2,3,4,5}.
Determine how many solutions satisfy the given equation.
a1x13+ a2x23+ a3x33+ a4x43+ a5x53=0
The coefficients are given integers from the interval [-50,50].
It is consider a solution a system (x1, x2, x3, x4, x5) that verifies the equation, xi∈[-50,50], xi != 0, any i∈{1,2,3,4,5}.
Determine how many solutions satisfy the given equation.
Input
The only line of input contains the 5 coefficients a1, a2, a3, a4, a5, separated by blanks.
Output
The output will contain on the first line the number of the solutions for the given equation.
Sample Input
37 29 41 43 47
Sample Output
654
Source
题目大意:给你一个方程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 24656 KB 469 ms C++ 859 B 2012-08-22 09:34:05 #include<stdio.h> #include<string.h> const int maxn=25000000;//50^4*2*2 char hash[maxn];//注意定义为char类型,否则会超内存 int main() { int a1,a2,a3,a4,a5; int i,j,k; int sum,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); } return 0; }