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 ;
}