POJ 1840 Eqs(哈希)

题目链接

题目大意:给出一个 a1*x1^3+ a2*x2^3+ a3*x3^3+ a4*x4^3+ a5*x5^3 = 0 的方程,读入a1,a2,a3,a4,a5这5个系数,求解这个方程的解的个数。系数 ai∈[-50,50]  自变量xi∈[-50,0)∪(0,50]

分析:这题有点类似Hdu1496,但是因为是3个立方相加,所以特别占内存。首先这题肯定不能枚举4个x的值,由方程计算得到第五个x的值,枚举四个x的值就是O(1e2^4)也就是 O(1e8)肯定是超时的。

所以考虑将方程移项得 :

a1*x2^3+a2*x2^3 = -a3*x3^3 - a4*x4^3 - a5*x5^3 。定义一个映射数组Hash,然后两层for循环枚举x2和x3的值,将方程左边的每个值所出现的次数用Hash数组存下来,注意,这里记录的是次数,而不是记录是否出现过,因为不能保证这是一个单射(1对1映射),可能会存在多对1的映射。

例如当 a1= a2 时,那么x1与x2两个值是可以交换位置的,这是两个不同的解,也就是多对1的情况了,如果是记录这个值是否出现过,会使得一部分解被遗漏(不能理解可以看后面的代码)。然后因为方程的右边可以产生的上界为50*50^3+50*50^3=12500000,由于是立方,所以这个值也可能为负数,因此Hash[]数组的的上界需要扩展到25000000,数组很大,所以肯定设置为全局的,并且int的话肯定会爆(用Hash表存是可以A的,但蒟蒻表示不会TAT),因为Hash数组只是需要记录出现的次数,这个值并不会很大,所以改为用char或者short存即可,这里为了方便,用short数组来存储。然后再三层for枚举x3,x4和x5的值得到方程右边的值,用答案值累加方程右边的值出现的次数,其实也就是看左边的值出现了几次,因为左右值相等的时候,就是方程成立的时候,所以也就得到了这个方程的解的个数,总复杂度就由O(n^4)降低到了O(n^2+n^3)。

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<cstdio>
#include<vector>
#include<cctype>
#include<cstring>
#include<utility>
#include<cstdlib>
#include<iomanip>
#include<iostream>
#include<algorithm>
#define Clear(x) memset(x,0,sizeof(x))
#define fup(i,a,b) for(int i=a;i<b;i++)
#define rfup(i,a,b) for(int i=a;i<=b;i++)
#define fdn(i,a,b) for(int i=a;i>b;i--)
#define rfdn(i,a,b) for(int i=a;i>=b;i--)
typedef long long ll;
using namespace std;
const int maxn = 25000000+7;

short Hash[maxn];

int main()
{
    int a1,a2,a3,a4,a5;
    while(scanf("%d%d%d%d%d",&a1,&a2,&a3,&a4,&a5)!=EOF)
    {
        Clear(Hash);
        for(int i=-50;i<=50;i++)
        {
            for(int j=-50;j<=50;j++)
            {
                if(i!=0&&j!=0)
                {
                    int sum=a1*i*i*i+a2*j*j*j;
                    if(sum<0) sum+=maxn;
                    Hash[sum]++;
                }
            }
        }
        int ans=0;
        for(int i=-50;i<=50;i++)
        {
            for(int j=-50;j<=50;j++)
            {
                for(int k=-50;k<=50;k++)
                {
                    if(i!=0&&j!=0&&k!=0)
                    {
                        int sum=-a3*i*i*i-a4*j*j*j-a5*k*k*k;
                        if(sum<0) sum+=maxn;
                        ans+=Hash[sum];
                    }
                }
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41311604/article/details/81603288
今日推荐