逆向思維,以及如何嚴謹地設定搜尋邊界

2021-08-17 08:09:12 字數 2030 閱讀 5046

昨天刷計蒜客,遇到這樣一道題:

等差數列

我把題目搬過來:

乙個等差數列是乙個能表示成 a,a+b,a+2b,...,a+nb(n=0,1,2,3,...)a,

a+b,

a+2b

,...

,a+n

b(n=

0,1,

2,3,

...)

的數列。

在這個問題中 a

a 是乙個非負的整數,b

b 是正整數。寫乙個程式來找出在雙平方數集合(雙平方數集合是所有能表示成 p2+q2p2

+q2 的數的集合) s

s 中長度為 n

n 的等差數列。

輸入包括兩行,第一行為 n(3≤n≤25)n(

3≤n≤

25) 要找的等差數列的長度。第二行是找到的雙平方數 p

p 和 q

q 的上界 m(0≤p,q≤m)m(

0≤p,

q≤m)

。輸出一行或者多行,如果沒有找到數列,輸出none。否則輸出乙個整數對a b(這些行應該先按 b

b 排序再按 a

a 排序)

題目讀完,我的第一反應就是深搜,因為它本質上還是在所有可能性大組合中搜尋符合條件的佇列。

於是風風火火就寫起來了:

//// main.cpp

// ari_prgr

//// created by horizon42 on 2018/3/20.

//#include #include #include #include #include #include using namespace std;

// 構造乙個結構體儲存a,b, 並過載它的 < 比較符號,以方便排序。

struct a_b

for (int i =cur+1; i<=maxn; ++i)

}int main()

}for(auto i = tmp.begin(); i!=tmp.end(); ++i)

cout《結果呢? 結果當然是超時了!!!

而且這已經是我絞盡腦汁減少遞迴次數提高效率的結果。折騰半天也就從通過一組編成了通過二組……

沒想到,正解竟然那麼暴力。

先看**:(**是我了解解題思想之後自己寫的)

//// main.cpp

// ari_prgr_check 逆向思維的應用

//// created by horizon42 on 2018/3/21.

//#include using namespace std;

bool checked[125001] = ; //標記某個數字是不是符合條件的平方數

int a[125001] = ; //儲存所有可能的a,也就是所有平方數

int main(int argc, const char * argv)

}//初始化a

for (int i=0,j=0; i<=m*m*2; ++i)

}bool none = true;//標記是否沒有結果

int b=1;

int max_b = (m*m*2)/(n-1);

//b也就是公差由小到大開始遍歷,有排序效果

for (; b<=max_b; ++b) {

//為當前的b公差搜尋可能的a

for (int i=0; a[i]+(n-1)*b<=m*m*2; ++i) { // a[i]<=m*m*2這種寫法 依然浪費了時間

//判斷是不是等差數列

bool is_checked = true;

for (int n=1; n**注釋得很清晰了,核心思想就是直接暴力搜尋所有符合條件的組合。但它之所以效率高,主要有3點:

使用乙個標記陣列,避免出現重複的平方數的同時,也方便在搜尋時判斷等差數列成不成立

判斷是否為等差數列時,用逆向思維,如果a[i]+n*b並沒有在標記陣列中被記錄,則說明這個組合不符合要求。

從b也就是公差的角度開始搜尋,節省了排序的時間。

可以說,受益良多。

賭神(逆向思維)

時間限制 c c 1秒,其他語言2秒 空間限制 c c 32768k,其他語言65536k 64bit io format lld 買定離手,買定離手!到底誰能捧盃本次新生賽?億電競的投資人 億大佬 向你介紹遊戲規則 你可以參與數次競猜,每次競猜都有兩個待選隊伍a和b 當然不是競猜新生賽的隊員哈 你...

逆向思維(域外箴言)

因閉口不言而讓別人以為你是傻瓜,比因為張嘴說話而證實別人的猜想,要明智得多。事先如果沒有充分的準備,我無法做好即興演講。一定要聽父母的話 當他們在場的時候。防止受 的好辦法很多,其中最保險的方法是做個膽小怕事的人。行善是偉大的 勸人行善更偉大,而且做起來也更容易。我從不讓學校生活干擾我學習真正的知識...

Flower 規律 逆向思維)

flower 傳送門 題解 逆向思維 規律 因為每次剪n 1,所以逆向就是控制n 1朵不變,每次增高1朵,直到所有等高,即所有的高度都等於最高的那一朵,記錄增高的次數為sum,反過來就是最高的那個減少sum,如果減少sum後小於1則不成立,大於等於1,則需要減少sum次。sum 每朵花與最高的差的和...