今天刷hdu题,刷到了哈希表,看了看别人写的,有看了看哈希表的相关视频,现在有了一个初步的理解。
题目链接:http://icpc.njust.edu.cn/Problem/Hdu/1496/
哈希表是一种查找算法,我们学过的简单查找,像顺序查找(直接for循环),二分查找,两者不约而同地都是通过提取数组中已经存好的值,与要查找的值去比较,最后找到需要的值,这种查找的方法很慢,尤其是在要查找的数组很大的情况下。那么哈希表就解决了这个问题,哈希表是通过空间换取时间的方式去提高查找效率。
例如,一个数组[1,2,4,6,8],我们可以开一个更大的数组来储存这些值,假如这个数组为a[10],那么我们以数组的元素值去储存以方便查找,我们让a[1]=1,a[2]=2,a[4]=4,a[6]=6,a[8]=8.那么当我们要查找我们需要的元素时我们就可以直接通过该元素值直接读取数组a[]对应的值,这个过程完全不需要查找,直接访问,显然要比我们学的简单查找高效的多。
不过实际上,以元素值作为下标来存储时,往往会出现重复的问题,具体有很多解决方法,我还没有学,不过对这道题来说,重复并不会造成问题。
我们还是来讨论这道题,如果我们去做四重for循环去算整个式子的和毫无疑问,肯定是超时的,我们可以将整个式子分为两个式子去算(只需要二重for循环),然后只要两个式子的值是相反的,那么它就是等式的一组解。我们把整个式子分为ax1x1+bx2x2和cx3x3+dx4x4两部分,分别用来两个数组去存。
xi的最大绝对值为100,a,b,c,d的最大绝对值为50,所以我们的最大数组下标为1000001,所以我们就开这样大小的两个数组。
按照哈希表的思想,我们以k(具体值参见代码)的绝对值作为下标,k>0我们就让arr1[k]++,k<=0时我们就让arr2[-k]++,第二次循环是只要k的绝对值相同且符号相反那么就表明两个式子相反即和为0,我们让sum记录解的数量。
最后输出16*sum为解的总数。
代码如下:
#include<iostream>
#include<algorithm>
using namespace std;
int arr1[1000001], arr2[1000001];
int main()
{
int a, b, c, d, k;
while (cin >> a >> b >> c >> d)
{
if (a > 0 && b > 0 && c > 0 && d > 0 || a < 0 && b < 0 && c < 0 && d < 0)//a,b,c,d同号时结果一定不为零直接输出
{
cout << 0 << endl;
continue;
}
memset(arr1, 0, sizeof(arr1));
memset(arr2, 0, sizeof(arr2));//初始化数组
for (int i = 1; i <= 100; i++)
{
for (int j = 1; j <= 100; j++)
{
k = a * i*i + b * j*j;
if (k > 0)
arr1[k]++;
else
arr2[-k]++;
}
}
int sum = 0;
for (int i = 1; i <= 100; i++)
{
for (int j = 1; j <= 100; j++)
{
k = c * i*i + d * j*j;
if (k < 0)
sum += arr1[-k];
else
sum += arr2[k];
}
}
cout <<16*sum << endl;
}
return 0;
}