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 ;

}

 

你可能感兴趣的:(HDU)