HDU-1496(哈希表)

Hash入门第一题

题意:

 

  1. 问题描述

  • 考虑具有以下形式的方程:

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

  • a,b,c,d是来自区间[-50,50]的整数和它们中的任何不能为0。

  • 这是考虑的溶液的系统(X1,X2,X3,X4),其验证方程,xi是从[-100,100]和XI的整数!= 0,任意i∈{1, 2,3,4}。

  • 确定满足给定方程的解决方案数量。

输入
输入包含几个测试用例。每个测试用例由包含4个系数a,b,c,d的单行组成,由一个或多个空格分隔。
文件结束。
 

产量
对于每个测试用例,输出包含解决方案数量的单行。

样本输入
1 2 3 -4
1 1 1 1

样本输出
39088
0


题目分析:
        最开始的想法会是从0-100里面找x1,x2,x3,x4, 4个任意不同组合,会用4重循环,然后用得到的值×16

  • 如果用Hash的思路的话

  • 1.用内存换时间 

  • 2.只需要两重循环,+Hash存储查找就行了。 

  • 3.将4重循环分解为两个两重循环

  • 4.查找满足条件的记录下来 

#include <stdio.h>
#include <memory.h>

int pin[101];//用来记录x(i)^2的值
int hash[2000003];//hash表的key值
 
int main(){
	int a, b, c, d;
	int sum;
	//pin 用来存储每个x(i)的可能值 
	for( int i = 1; i <= 100; i++ )
		pin[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(int i = 1; i<=100;i++){
			for(int j=1;j<=100;j++){
				//构造哈希函数让每个值都有一个不同的key 
				hash[a*pin[i]+b*pin[j]+1000000]++;
			}
		}
		sum = 0;
		for(int i= 1;i<=100;i++){
			for(int j=1;j<=100;j++){
				//查找是否有满足条件的key,有的话记录+1 
				sum += hash[-(c*pin[i]+d*pin[j])+1000000];
			}
		}
		printf("%d\n",sum*16);
	}
	return 0;
} 

当然可以来一个它的优化版本了

因为两层循环最多只可能产生10000个不同的结果,开200w的数组将会浪费很多初始化的时间,所以开小数组+处理冲突会比较好

//由于100 * 100 只有10000个不同的结果,
//因此只需要大于10000就可以了 
//因此本题是可以根据这个条件对上面那个代码进行优化的
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h> 
#define MAX  50001

int f[MAX],g[MAX];

int hash(int k){
	int t = k%MAX;
	if( t < 0 )
		t += MAX;
	//这个是解决冲突的核心, 
	//前面的f[t]用来将占位的位置后移  后面那个g[t]的存在当然是为了查找
	while(f[t]!=0 && g[t]!=k){
		t = (t+1)%MAX;
	}
	return t;
}

int main(){
	int a, b, c, d, i, j,s,p, sum=0, t[101];
	for( i=1;i<=100;i++)
		t[i] = i*i;
	while(~scanf("%d%d%d%d",&a,&b,&c,&d)){
		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));
		
		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]++;
			}
		}
		sum = 0; //用来计数的 
		for( i=1;i<=100;i++){
			for( j=1;j<=100;j++){
				s = -(c*t[i]+d*t[j]);
				p = hash(s);
				//如果p这个数在f数组中存在则计数加1 
				sum += f[p]; 
			}
		}
		printf("%d\n",sum*16); 
	} 
}

猜你喜欢

转载自blog.csdn.net/Dream_your/article/details/81234014