Hdu 1496 Equations

Problem地址:http://acm.hdu.edu.cn/showproblem.php?pid=1496

 

此题可以用哈希数组求解,至于什么是哈希,可以先看以下这篇推荐文章,写得挺不错的。

推荐:http://www.cnblogs.com/yangecnu/p/Introduce-Hashtable.html#undefined

 

方法一:a*x1^2+b*x2^2+c*x3^2+d*x4^2=0

可以看作:a*x1^2+b*x2^2 = (c*x3^2+d*x4^2)*(-1)

其中:a,b的大小都在正负50之间,而x则为正负100之间(除了0)

那么左边的大小范围+-1000000,其实右边也一样。

那么就可以用两个hash数组,假设为hash1[], hash2[]

直接将计算结果作为key,那hash1[ key ] 不等于0 时,就代表左边可以计算出key这个值,

hash2[key]如果也不等于0,也就是右边也可以计算出这个值,即间接说明等式a*x1^2+b*x2^2+c*x3^2+d*x4^2=0成立

但此时key可能为负数,所以为了更好的与数组配合,两边同加上一个数字2000000,这样两边既能保持平衡,又能使任一边计算结果不为0

#include <iostream>
#include <cstring>
#include <cstdio>

using namespace std;

const int MAXN = 2000000;
int hash1[ MAXN+5];
int hash2[ MAXN+5];
const int CUR = 1000000;

int main()
{
    int a, b, c, d;
    int i, j;
    int cases=0;
    while( scanf("%d%d%d%d", &a,&b,&c,&d)!=EOF )
    {
    	// a,b,c,d都大于0或都小于0的情况可以直接得出结果为0
        if( a>0 && b>0 && c>0 && d>0 )
        {
            printf("0\n");
            continue;
        }
        if( a<0 && b<0 && c<0 && d<0 )
        {
            printf("0\n");
            continue;
        }
       // 数组初始化
        memset( hash1, 0, sizeof(hash1) );
        memset( hash2, 0, sizeof(hash2) );

        for( i=1;i<=100;i++ )
        {
            for( j=1;j<=100;j++ )
            {
                hash1[ i*i*a + j*j*b + CUR ]++;
                hash2[ CUR - i*i*c - j*j*d ]++;
            }
        }

        cases = 0;
        for( i=0;i<=MAXN+3;i++ )
            cases = cases + hash1[i] * hash2[i];
        printf( "%d\n", cases*16 );
        // 要乘以16 ,因为刚才计算时,x1,x2,x3,x4都只算了为正的情况,但这4个变量其实每个都可正可负的
    }
}

 

 

 

方法二:其实也差不多,但主要在空间的利用上,因为x1^2最多有100种情况, x2^2也最多有100种情况,那么每边最多有10000种情况,那么上一种方法对空间实在是太浪费了。所以构造一个好的哈希函数,能节省好多空间。

#include <iostream>
#include <cmath>
#include <cstdio>

using namespace std;

const int PRIME = 9973;
const int KEEP_POS_MAXN = 2000000;
const int ARRAY_MAXN = 10000;

typedef struct Node{
		Node *next;
		int value;
		int times;
		Node(){
			times = 1;
			next = NULL;
		}
}Node;

Node hash[ARRAY_MAXN];

int GetKey( int value );
void InsertValue( int value );
Node *QueryValue( int value );
void FreeNode( Node * );

int main() {
	int a, b, c, d;
	while( scanf( "%d%d%d%d", &a, &b, &c, &d )!=EOF ) {
		// a,b,c,d 都大于0或都小于0可以直接得出结果为0
		if( a>0 && b>0 && c>0 && d>0 ) {
			printf( "0\n" );
			continue;
		}
		if( a<0 && b<0 && c<0 && d<0 ) {
			printf( "0\n" );
			continue;
		}
		
		
		int x1, x2;
		for( x1=1; x1<=100; x1++ ) {
			for( x2=1;x2<=100;x2++ ) {
				InsertValue( a*x1*x1+b*x2*x2+KEEP_POS_MAXN );
			}
		}
		int x3, x4;
		int total = 0;
		Node *target = NULL;
		for( x3=1; x3<=100; x3++ ) {
			for( x4=1;x4<=100;x4++ ) {
				target = QueryValue( (c*x3*x3+d*x4*x4)*(-1)+KEEP_POS_MAXN );
				if( target != NULL ) {
					total += target->times;
				}
			}
		}
		printf( "%d\n", total*16 );	
		for( int i=0; i<ARRAY_MAXN; i++ ) {
			// 释放洁点空间的操作,不使用也能AC;但使用与不使用的空间使用情况差距会很大
			FreeNode( hash[i].next );
			hash[i].next = NULL;
		}
	}
	return 0;
}

int GetKey( int value ) {
	return value % PRIME;
}

void InsertValue( int value ) {
	int key = GetKey( value );
	Node *target = &hash[ key ];
	while( target->next != NULL ) {
		target = target->next;
		if( target->value == value ) {
			target->times ++;
			return ;
		}
	}
	
	Node *node = new Node;
	node->value = value;
	target -> next = node;
	return ;
	
}

Node *QueryValue( int value ) {
	int key = GetKey( value );
	Node *target = &hash[ key ];
	
	do{
		target = target->next;
	}while( target!=NULL && target->value!=value );
	
	return target;
}

void FreeNode( Node *target ) {
	if( target!=NULL ) {
		FreeNode( target->next );
		delete target;
	}
	return ;
}

 

posted @ 2015-02-08 21:14  Emerald  阅读(236)  评论(0编辑  收藏  举报