且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

HDOJ1496 Equations【Hash】

更新时间:2022-08-26 15:28:16

题目大意:

有一个等式,

a*x1^2+b*x2^2+c*x3^2+d*x4^2=0,

a、b、c、d是[-50,50]之间的非零整数,

有一组解析(x1,x2,x3,x4),其中xi是[-100,100]之间的非零整数,

求有多少组解满足上式;

输入:多组测试用例,每组测试用例包含4个数:a,b,c,d,他们之间用一个或多个空格隔开,EOF结尾;

输出:每组测试用例解的个数;

==========基本思路=========

4个循环嵌套,回溯;但是这样的复杂度是n^4,在本题中就是10000 0000数量级的~

==========改进思路=========

把两项移到右边,就变成了左边两项与右边两项相等的式子;

这样只要分别计算左右两边相等的可能性即可,这样的复杂度就是10000数量级了~

==========================

a*x1^2 最大是50*10000 = 500000,其他三项也是,同理,最小是-500000;

两项的最大就是1000000,最小就是-1000000,这样就需要一个2000000的hash表来存储了;

但是要注意的是,最后hash表中存储的解得个数并不是最后结果,因为a、b、c、d四项可以互换位置,所以最后要乘以2^4 = 16才是解的个数;

Problem : 1496 ( Equations )     Judge Status : Accepted
RunId : 7413352    Language : C    Author : qq1203456195
Code Render Status : Rendered By HDOJ C Code Render Version 0.01 Beta

 

HDOJ1496 Equations【Hash】
#include <stdio.h>
#include <string.h>

int arr[101];
int hash[2000003];
int main()
{
    int a,b,c,d;
    int i,j,sum;
    for (i=1;i<101;i++)    arr[i] = i*i;
    while (scanf("%d%d%d%d",&a,&b,&c,&d)!=EOF)
    {
        if ((a>0 && b>0 && c>0 && d>0) ||
            (a<0 && b<0 && c<0 && d<0))
        {
            printf("0\n");
            continue;
        }
        memset(hash,0,sizeof(hash));
        for (i=1;i<=100;i++)
        {
            for (j=1;j<=100;j++)
            {
                hash[a*arr[i] + b*arr[j] + 1000000]++;
            }
        }
        sum = 0;
        for (i=1;i<=100;i++)
        {
            for (j=1;j<=100;j++)
            {
                sum += hash[-(c*arr[i] + d*arr[j]) + 1000000];
            }
        }
        printf("%d\n",sum<<4);
    }
    return 0;
}
HDOJ1496 Equations【Hash】

 =======再次改进=======

很明显,双重循环最多产生10000个数,所以开2000000个空间的数组明显是浪费了,怎样优化呢?1、数组,2、hash函数,3、冲突处理

开小数组是必须的,但是并不是越小越好,因为还要考虑冲突的现象,但是具体取多少的?HDUACM的课件中开的是50021,这是一个较大的素数,这样key的位置就可以通过比较常用的除模取余方法来确定了。其实hash函数以及处理冲突的方法有很多,没有固定的方法。

下边是HDUACM课件中使用的方法:

HDOJ1496 Equations【Hash】
int hash(int k)
{
    int t=k%MAX;
    if(t<0)
        t+=MAX;
    while(f[t]!=0&&g[t]!=k)
        t=(t+1)%MAX;
    return t;
}
HDOJ1496 Equations【Hash】

hash函数:t = k%MAX

处理冲突的方法:t = (t+1)%MAX

完整代码:f数组用来统计个数,g数组用来记录值;

HDOJ1496 Equations【Hash】
// by laili
#include<stdio.h>
#include<memory.h>

#define MAX 50021

int f[MAX],g[MAX];

int hash(int k)
{
    int t=k%MAX;
    if(t<0)
        t+=MAX;
    while(f[t]!=0&&g[t]!=k)
        t=(t+1)%MAX;
    return t;
}

int main()
{
    int a,b,c,d,p,i,j,s,n,t[101];
    for(i=1;i<=100;i++)
        t[i]=i*i;
    while(scanf("%d%d%d%d",&a,&b,&c,&d)>0)
    {
                        ……
    }
}
HDOJ1496 Equations【Hash】

while中代码:

HDOJ1496 Equations【Hash】
if(a>0&&b>0&&c>0&&d>0||a<0&&b<0&&c<0&&d<0)
        {
            printf("0\n");
            continue;
        }
        memset(f,0,sizeof(f));
        n=0;
        for(i=1;i<=100;i++)
            for(j=1;j<=100;j++)
            {
                s=a*t[i]+b*t[j];
                p=hash(s);
                g[p]=s;
                f[p]++;
            }
        for(i=1;i<=100;i++)
            for(j=1;j<=100;j++)
            {
                s=-(c*t[i]+d*t[j]);
                p=hash(s);
                n+=f[p];
            }
        printf("%d\n",n*16);
HDOJ1496 Equations【Hash】

 


本文转自ZH奶酪博客园博客,原文链接:http://www.cnblogs.com/CheeseZH/archive/2012/12/18/2824091.html,如需转载请自行联系原作者