HDOJ1496 Equations(整数hash)

hash的基础思想:

1.哈希表(散列表)的基本原理:

使用一个下标范围比较大的数组来存储元素,一般通过设计一个函数(哈希函数,即散列函数),使得每个元素的关键字都与一个函数值(即数组下标)相对应,然后用该数组单元来存储对应元素。

2.hash表函数的构造:

最常见的方法:除余法
H(k ) = k mod p (p一般选取适当大的素数)

3.处理冲突

由于不能够保证每个元素的关键字与函数值是一一对应的,因此很有可能出现如下情况:“对于不同的元素关键字,Hash函数计算出了相同的函数值”,这就是产生了所谓的“冲突”。
换句话说,就是Hash函数把不同的元素分在了相同的下标单元。

常用方法:线性探测再散列技术
即:当 h(k)位置已经存储有元素的时候,依次探查 (h(k)+i) mod S, i=1,2,3…,直到找到空的存储单元为止。其中, S为 数组长度。
特别地,如果将数组扫描一圈仍未发现空单元,则说明哈希表已满,这会带来麻烦,但是,该情况完全可以通过扩大数组范围来避免。

4.hash表的基本操作

Hash表初始化(0或-1或其它)
哈希函数运算
插入元素(包含冲突解决)
定位(需考虑可能冲突的情况)
——————————————————————————————————————————————————————————
题意:
方程式为a*x1^2+b*x2^2+c*x3^2+d*x4^2=0
a, b, c, d 是 [-50,50] 区间内非零整数.
( x1,x2,x3,x4 ) 是[-100,100]区间内的非零整数。
问的是方程的解的情况有几种。

思路分析:
hash的妙处就在于实现了每一个元素的关键值都和数组的下标相对应。
先对x1和x2进行枚举,存在的存进hash表中,然后接下来枚举x3和x4,如果恰好和前面的为相反数,那么ans+上前面出现的次数.
由于求[-100,100]之间的非零整数,也就是说100*100*2=20000的一维数组就可以了。
PS:
用枚举1~100而负半区域不考虑,节省枚举数,最后答案因为四个数全部都是正的,而实际上都有每个数都有正有负,故答案*16

#include 
#include 
#include 

using namespace std;

const int N = 2000005;

int main()
{
    // freopen("in.txt", "r", stdin);
    int a, b, c, d;
    int Hash[N];
    while(~scanf("%d%d%d%d", &a, &b, &c, &d))
    {
        if(a * b > 0 && b * c > 0 && c * d > 0)
        {
            printf("0\n");
            continue;
        }
        memset(Hash, 0, sizeof(Hash));
        for(int i = 1; i <= 100; i ++)
            for(int j = 1; j <= 100; j ++)
                Hash[a * i * i + b * j * j + 1000000] ++;
        int ans = 0;
        for(int i = 1; i <= 100; i ++)
            for(int j = 1; j <= 100; j ++)
                ans += Hash[- c * i * i - d * j * j + 1000000];
        printf("%d\n", 16 * ans); //我们计算的全是真的,实际上还有负的,只要在原结果*16即可。
    }
    return 0;
}

你可能感兴趣的:(HDOJ1496 Equations(整数hash))