POJ 1840 Eqs

76 篇文章 0 订阅
16 篇文章 1 订阅

唉,我的入门“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: 
a1x1 3+ a2x2 3+ a3x3 3+ a4x4 3+ a5x5 3=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


题目大意:给你一个方程 a1x1 3 + a2x2 3 + a3x3 3 + a4x4 3 + a5x5 3 =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+ a5x5 )
                            容易知道  的范围肯定比   的范围小,而二者又要相等,所以以前者的范围来确立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;
}



 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值