給定乙個四元二次方程:
$ax1^2+bx2^2+cx3^2+dx4^2=0$
試求$−1000≤x1,x2,x3,x4≤1000$非零整數解的個數。
$−10000≤a,b,c,d≤10000$
輸出解的個數。
解法:
首先這道題直接用網上hdu1496的板子過不去,原因是1e10的陣列開不了那麼大的。所以這裡只能換思路。新思路如下(很典型的折半列舉,也就是meet-in-middle):
把x1,x2的答案存下來(存在乙個2000*2000的陣列裡面),然後排序當然這裡用陣列會稍顯笨拙,可以用map,卡時間可以過。二分查詢這個陣列裡面有多個數x了
$ax_1^2+bx_2^2=-(cx_3^2+dx_4^2)$
左邊式子的答案我們已經存下來了,接下來算右邊的
右邊答案算出來過後,我們直接在左邊陣列裡面二分有多少個一樣的數值,答案加上這個數值就ok了
注意s[a*i*i + b*j*j]++
會爆int,因此需要將a改為long long
**如下:
1 #include2 #include3 #include4using
namespace
std;
5 typedef long
long
ll;6 maps;78
intmain()
15for (ll i = 1; i <= 1000; i++) 20}
21 ll sum = 0;22
for (ll i = 1; i <= 1000; i++) 28}
29 printf("
%lld\n
", 16*sum);30}
31return0;
32 }
上面說了卡常數不是很嚴的做法,如果卡常數很嚴的話,比如x的範圍變到4000,map就會t掉,這裡直接採用hash的方法
例題:uva1152:4 values whose sum is 0
1//hash數字編碼
2 #include3 #include4 #include5 #include6 #include7
using
namespace
std;
8 typedef long
long
ll;9 maps;
10int a[4005], b[4005], c[4005], d[4005
];11
intn, t, cnt;
1213
//w[i]表示第i個結點儲存的數(也就是a+b),st[i]表示第i個結點有多少種表示方法
14const
int hashsize = 1000003;15
int hd[hashsize], nxt[16000005], w[16000005], st[16000005
]; 16
void
in(int
x) 23 u =nxt[u];24}
25 nxt[++cnt] =hd[h];
26 hd[h] =cnt;
27 w[cnt] =x;
28 st[cnt] = 1;29
}3031int srch(int
x) 38
return0;
39}4041
intmain()
50for (ll i = 0; i < n; i++) 54}
55 ll sum = 0;56
for (int i = 0; i < n; i++) 60}
61 printf("
%lld\n
", sum);
62if (t) printf("\n"
);63}64
return0;
65 }
折半列舉0 5
0.5table of contents 折半列舉 常見型別 具體題目 poj2785 poj3977 noip2014模擬賽 某種密碼 password include include include include include include define l long long defin...
折半列舉(雙向搜尋)
各有n個整數的四個數列a b c d。要從每個數列中各取乙個數,使四個數的和為0。求出這樣組合的個數。輸入n 6 a b c d 從4個數列中選擇共有n4種情況,全部判斷一遍不可行。不過將它們對半分成ab和cd再考慮,就可以快速解決了。從2個數列中選擇的話只有n2種組合,所以可以進行列舉。先從a b...
問題 A 賭徒 折半列舉查詢
題目描述 有n個賭徒打算賭一局。規則是 每人下乙個賭注,賭注為非負整數,且任意兩個賭注都不相同。勝者為賭注恰好是其餘任意三個人的賭注之和的那個人。如果有多個勝者,我們取賭注最大的那個為最終勝者。例如,a,b,c,d,e分別下賭注為2 3 5 7 12,最終勝者是e,因為12 2 3 7。輸入輸入包含...