题目:
Description
Consider equations having the following form:
a1x13+ a2x23+ a3x33+ a4x43+ a5x53=0
The coefficients are given integers from the interval [-50,50].
It is consider a solution a system (x1, x2, x3, x4, x5) that verifies the equation, xi∈[-50,50], xi != 0, any i∈{1,2,3,4,5}.
Determine how many solutions satisfy the given equation.
Input
a1x13+ a2x23+ a3x33+ a4x43+ a5x53=0
The coefficients are given integers from the interval [-50,50].
It is consider a solution a system (x1, x2, x3, x4, x5) that verifies the equation, xi∈[-50,50], xi != 0, any i∈{1,2,3,4,5}.
Determine how many solutions satisfy the given equation.
Input
The only line of input contains the 5 coefficients a1, a2, a3, a4, a5, separated by blanks.
Output
The output will contain on the first line the number of the solutions for the given equation.
Sample Input
37 29 41 43 47
Sample Output
654
本题直接想到的是“暴力破解法”直接枚举。但是用于方程原型复杂度较高,N^5,N的规模为100,直接算的话要计算100^5次方程,肯定会超时。
所以要将方程做一个变形,变为:
-(a1x13+ a2x23)==a3x33+ a4x43+ a5x53。
现在可以暴力破解了,分别把两边的所有取值存入数组(由于本题只要求对解进计数,所以一维就足够了),再作比较。
作暴力破解时,可以把Xi看做互相独立的。所以可以在一个三层的循环中进行,即外面两层循环用来枚举方程左边的值,最里层枚举方程右边的值。
(这样复杂度就变成了N^3.)
破解出方程两边的所有取值之后,接下来就是匹配解了。
有两种策略,一是,由左边的值匹配右边的;另一是,由右边的值匹配左边的。由于需要对被匹配的一边的值序列进行排序,而考虑到整个过程的效率,必须尽可能的使被排序的序列较长(此时效率更高)。所以,左配右的策略更好。
排序,可以用 STL 的 sort ,或者C语言的 qsort;(sort的复杂度是O(NlogN),qsort的最佳效率为O(NlogN))
匹配过程是:对于任意一个左边的取值,如果右边的值集合里有 n 个和它相同的值,则解数目加 n ,所以可以使用 STL 的for_each(),只须自己再完成一个函数,这个函数实现对任意 的一个值,找出它在右边(集合)出现几次。
用STL可以完美的实现。看看AC的源码,就知道STL有多么好用。
#include <cstdio>
#include <algorithm>
using namespace std;
#define cub(x) (x*x*x)
int alist[10000], blist[1000000];
int *aend=alist, *bend=blist;
int rescnt=0;
// void printi(int n) { printf("%d\n", n); }
void findroot( int an );
int main()
{
// freopen("aaa.txt","r",stdin);
int a[5];
for (int i=0; i<5; i++) scanf("%d", a+i);
for (int i=-50; i<=50; i++) if(i)
for (int j=-50; j<=50; j++) if(j)
{
*(aend++) = -(a[0]*cub(i) + a[1]*cub(j) );
for (int k=-50; k<=50; k++) if(k){
*(bend++) = a[2]*cub(i) + a[3]*cub(j) + a[4]*cub(k);
}
}
// sort(alist, aend);
sort(blist, bend);
// for_each(alist, aend, printi );
// for_each(blist, bend, printi );
for_each( alist, aend, findroot );
printf("%d\n", rescnt);
return 0;
}
void findroot(int an)
{
int* ipl = lower_bound(blist, bend, an);
if (ipl != bend ) {
for( ; ; ipl++){
if ( *ipl > an ) return;
rescnt++;
}
}
}