P3704解方程
时间限制 : - MS 空间限制 : 65536 KB
评测说明 : 时限1000ms
问题描述
告诉你A1,A2,A3,A4,A5,计算出下面方程在[-50,50]内的解的数量:
A1*X1^3+ A2*X2^3+ A3*X3^3+ A4*X4^3+ A5*X5^3=0
要求Xi!=0
输入格式
一行,5个空格间隔的整数,表示A1,A2,A3,A4,A5
输出格式
一个整数,表示解的个数
样例输入
37 29 41 43 47
样例输出
654
提示
-50<=Ai<=50
-50<=Xi<=50且Xi!=0
来源 Romania OI 2002
据说要用哈希
但其实用哈希很虚,因为解与解之间有可能重复(详情见后)
而且我曾经立下毒誓,以后绝对不会用哈希
解题吧…
这道题目其实是很暴力的
但是不能盲目暴力
暴力是要讲究方法的
所以叠五层循环的智障方法我们就不讲了
因此我们只叠2+3层(很明显的暴力优化)
(看到这里不知道你们有没有思路,如果有的话就自己再去做一次,毕竟自己想出来的总是好很多)
方程变形,左边放两个未知数,右边放三个
a*x1^3+b*x2^3=-c*x3^3-d*x4^3-e*x5^3
然后暴力枚举x1,x2,记录左边的值(mark数组记录)
然后再暴力枚举x3,x4,x5,寻找右边的值在mark数组当中的值,加进res里头
然后就求出来啦!!
注意
①左边的值是很有可能重复的(毕竟二元),所以mark数组记录的不是这个数字存在与否,而是出现的次数,因此不能用bool,但是又不能爆空间,所以建议用short(可能char也可以吧)
②开数组的大小问题
因为右边的值一定要等于左边的值,所以我们只需要考虑左边的值的取值范围
于是我们就有了50*50*50*50,但这只是a从1到50的,为了避免负数的情况,我们需要*2(因为负数>=-50*50*50*50,通过加50*50*50*50的可以避免)
因为有两个数所以再*2
结果就是25000000,这就是mark数组的大小(要稍微开大一点点)
③有个小细节,虽然我不说应该都能够通过跑样例得出,但还是说一下
就是题目当中加黑了的x!=0(需要特判)
就是这样了
是不是很暴力
附上代码
#include <iostream>
#include <cstdio>
using namespace std;
short mk[25001234];
int res=0;
int a,b,c,d,e;
int main()
{
scanf("%d%d%d%d%d",&a,&b,&c,&d,&e);
for(int xd=-50;xd<51;xd++)
for(int xe=-50;xe<51;xe++)
mk[-xd*xd*xd*d-xe*xe*xe*e+12500000]++;
for(int xa=-50;xa<51;xa++)
for(int xb=-50;xb<51;xb++)
for(int xc=-50;xc<51;xc++)
{
add=xa*xa*xa*a+xb*xb*xb*b+xc*xc*xc*c;
if(mk[add])res+=mk[add];
}
printf("%d",res);
}