Eqs poj1840

    数字哈希,原式变形为a1*x1^3+a2*x2^3=-(a3*x3^3+a4*x4^3+a5*x5^3),所以只需判断左右两边相等即可。

具体做法,先枚举出左式可得到的值,存入hash中,然后再枚举右式,若在hash中有该值,则count++。

//要使原式等于0,可将原式拆成左右两式,然后判断左右两边相等
#include<iostream>
#include<cstdio>
#include<vector>

using namespace std;
const int M=20001;
vector<int>hash[M];//此处采取的取模哈希

int main()
{
	int a[5],i,j,k,t,tmp,cnt;
	while(~scanf("%d%d%d%d%d",&a[0],&a[1],&a[2],&a[3],&a[4]))
	{
		for(i=0;i<M;i++)
			hash[i].clear();

		for(i=0;i<5;i++)//处理,将系数全部变为正数,不影响最后的结果(这样做为了后面构造的递减函数)
			if(a[i]<0)
				a[i]=-a[i];
		for(i=-50;i<=50;i++)
		{
			if(i==0)
				continue;
			for(j=50;j>=-50;j--)
			{
				if(j==0)
					continue;
				tmp=a[0]*i*i*i+a[1]*j*j*j;
				if(tmp<0)
					break;//递减函数,所以可以直接break
				hash[tmp%M].push_back(tmp);//只处理正数,后面同理
			}
		}
		cnt=0;
		for(i=-50;i<=50;i++)
		{
			if(i==0)
				continue;
			for(j=-50;j<=50;j++)
			{
				if(j==0)
					continue;
				for(k=50;k>=-50;k--)
				{
					if(k==0)
						continue;
					tmp=a[2]*i*i*i+a[3]*j*j*j+a[4]*k*k*k;
					if(tmp<0)
						break;
					for(t=0;t<hash[tmp%M].size();t++)
						if(hash[tmp%M][t]==tmp)
							cnt++;
				}
			}
		}
		printf("%d\n",cnt*2);
	}
	return 0;
}


 

你可能感兴趣的:(Eqs poj1840)