方程的解數
問題描述
已知乙個n元高次方程:
其中:x1, x2,
…,xn
是未知數,
k1,k2,
…,kn
是係數,
p1,p2,…pn
是指數。且方程中的所有數均為整數。
假設未知數1≤
xi ≤
m, i=1,,,n
,求這個方程的整數解的個數。
輸入檔案(equation.in)
檔案的第
1行包含乙個整數n。第
2行包含乙個整數m。第
3行到第
n+2行,每行包含兩個整數,分別表示ki和
pi。兩個整數之間用乙個空格隔開。第
3行的資料對應
i=1,第
n+2行的資料對應
i=n。
輸出檔案(equation.out)
檔案僅一行,包含乙個整數,表示方程的整數解的個數。
輸入樣例 3
150
1 2
-1 2
1 2
輸出樣例
178
約束條件
1<=n<=6,1<=m<=150;
方程的整數解的個數小於231。
★本題中,指數pi(i=1,2,……,n)均為正整數。
下面我們來仔細分析下面這個問題:
題目要求出給定的方程解的個數,這個方程在最壞的情況下可以有
6個未知數,而且次數由輸入決定。這樣就不能利用數學方法直接求出解的個數,而且我們注意到解的範圍最多
150個數,因此恐怕只能使用列舉法了。最簡單的思路是窮舉所有未知數的取值,這樣時間複雜度是
o(m^6).,
這個複雜度是無法承受的
.看來只有另闢蹊徑了.
因此需要尋找更好的方法,自然想到能否縮小列舉的範圍呢?
可以
僅僅通過列舉
3個未知數的值來找到答案
,這樣一來
, 前一半式子的和值
s 可以確定,這時只要列舉後
3 個數的值,檢查他們的和是否等於
-s 即可。這樣只相當於在
o(m^3)
前面加了乙個係數,當然還需要預先算出1 到
150
的各個冪次的值.
想到了這裡,問題就是如何迅速的找到某個
s 是否曾經出現過,以及出現過了多少次,於是就變成了
"某個元素是否在給定集合中
"這個問題
,所以我們選擇用使用雜湊表解決這個問題。雜湊函式的構造我們採用除餘法:,即
h(k ) = k mod p,這裡p
我們選擇乙個大素數
4000037.
程式中
mid變數
=n/2,
首先列舉前
n/2的和值
s,並將
s值儲存在雜湊表中
,我們不僅要記錄s的值
,同時我們還用乙個陣列
amount
記錄某個
s值出現的次數
.然後計算多項式後
n/2項的和的相反數
,再在雜湊表中尋找是否有與之相等的s值
,若相等則將相等的
s值對應的
amount
值相加,
就是答案.
#include
#include
#include
#define max 4000037 //雜湊函式中的大素數
using namespace std;
long answer[max],amount[max],use[max];//answer[i]是雜湊表,amount[i]表示 s出現的次數,use[i]表示雜湊表中該位置不位空
long mid;
long k[6],p[6];//k[i]是各項的係數,p[i]是各項的指數
long n,m,total;//n,m是題目中的約束條件,total是結果
long locate(long s)//雜湊表的定位函式
return h;
} void insert(long s)//雜湊表的插入函式
amount[posi]++;
}
void firsthalf(long d,long s)//計算多項式前n/2項的和,儲存在雜湊表中
long t;
for (long i=1; i<=m; i++)
方程的解數 雜湊表的應用
方程的解數 很經典的雜湊應用,先轉過來,有時間慢慢研究 問題描述 已知乙個n元高次方程 其中 x1,x2,xn是未知數,k1,k2,kn是係數,p1,p2,pn是指數。且方程中的所有數均為整數。假設未知數1 xi m,i 1,n,求這個方程的整數解的個數。輸入檔案 equation.in 檔案的第1...
方程的解數
蒜頭君在求解乙個 n n 元的高次方程 displaystyle k 1x 1 k 2x 2 ldots k nx n 0k1 x1p 1 k2 x 2p2 kn x npn 0其中 x 1,x 2,ldots,x nx1 x2 xn 是未知數,k 1,k 2,ldots,k nk1 k2 kn 是...
方程的解數
問題描述 蒜頭君在求解乙個 n 元的高次方程 假設未知數 1 xi m,i 1 n。你能幫蒜頭君算出這個方程的整數解個數嗎?輸入格式 第一行輸入乙個整數 n 1 n 4 第二行輸入乙個整數 m 1 m 150 第 3 行到第 n 2 行,每行輸入兩個整數,分別表示 k k 20 pi 1 pi 4 ...