題目:
Description
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
Output
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++;
}
}
}