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 "); continue; } if( a<0 && b<0 && c<0 && d<0 ) { printf("0 "); 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 ", 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 " ); continue; } if( a<0 && b<0 && c<0 && d<0 ) { printf( "0 " ); 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 ", 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 ; }