題目描述
現在有四個棧,其中前三個為空,第四個棧從棧頂到棧底分別為1,2,3,…,n。每乙個棧只支援一種操作:彈出並壓入。它指的是把其中乙個棧a的棧頂元素x彈出,並馬上壓入任意乙個棧b中。但是這樣的操作必須符合一定的規則才能進行。規則1:a棧不能為空。規則2:b棧為空或x比b棧棧頂要小。
對於給定的n,請你求出把第四個棧的n個元素全部移到第乙個棧的最少操作次數。
由於最少操作次數可能很多,請你把答案對1000007取模。
輸入輸出格式
輸入格式:
一行,乙個n
輸出格式:
一行,乙個正整數,為把最少操作次數 mod 1000007的值
輸入輸出樣例
輸入樣例#1:
2 輸出樣例#1:
3 說明
對於30%的資料,n<=8
對於60%的資料,n<=60
對於100%的資料,n<=2*10^9
此題實質上是hanoi四塔問題。
那麼hanoi四塔問題是不是可以通過三塔問題的結論來解決呢?答案是:可以,首先要知道,三塔問題是借助1個中間柱完成轉移,四塔問題是借助2個中間柱完成轉移,以上兩句話看似是廢話,其實很重要!
四塔問題可以轉化為:對於n個盤子的四塔問題,先將j(0<=j<=n)個盤子通過兩個中間柱(乙個中間柱,乙個目標柱)移動到另乙個目標柱,然後將n-j個盤子通過乙個中間柱移動到目標柱,最後將j個盤子通過兩個中間柱(乙個起始柱,乙個中間柱)轉移到目標柱
遞推方程:h[i]表示三塔問題的結論,即i個盤子通過乙個中間柱轉移需要多少步。f[i]表示四塔問題的結果,即i個盤子通過兩個中轉柱移動到4號柱需要多少步。
則,f[i] = min(1<=i<=n;0<=j<=i)
以上方程的複雜度為o(n^2),是比較低效的方法。那麼,有沒有更為優化的方法呢?
答案是有的,我們可以做到o(n),但是沒有用。上述演算法而言,我們都是要通過比較大小找出最小值的,且不論h[i]超不超int的問題,我們這題,每次%1000007後,我們根本無法保證找到的最小的就是最小的,因為有可能1000008%1000007<1000006%1000007,因為取模運算的存在。
怎麼辦?找乙個新的規律,f[i],表示i個盤子的四塔問題的解。我們通過求出f[i]的值,發現了乙個新的規律:
f[1] : 0 +2^0=1;
f[2] : 1 +2^1=3;
f[3] : 3 +2^1=5;
f[4] : 5 +2^2=9;
f[5] : 9 +2^2=13;
f[6] : 13+2^2=17;
f[7] : 17+2^3=25;
f[8] : 25+2^3=33;
f[9] : 33+2^3=41;
f10] : 41+2^3=49;
f[11]: 49+2^4=65;
即,f[i]-f[i-1]的值是有規律的,1個2^0,2個2^1,3個2^2,4個2^3,5個2^4以此類推。所以很容易寫出**,於是這題就這麼迎刃而解了。
#include
using namespace std;
long long n,k,v,ans,mo=1e6+7;
int main()
printf("%lld",(ans+n*v)%mo);
return
0;}
漢諾4塔 洛谷 P1573 棧的操作
首先,看出本題的題目原型是hanoi四塔。其次,想出動規方程 e i min 2 e j f i j 1 j i 其中f為hanoi三塔的結果,e為hanoi四塔的結果 最後 找規律。發現e相鄰兩數的差為 1,2,2,4,4,4,8,8,8,8,16,16,16,16,16,利用此性質解決100 的...
P1044 棧(洛谷) 動態規劃
洛谷傳送門 p1044 這一題是一題很經典的動態規劃。在這裡我們知道,對於已經排到佇列中的元素對剩下的元素的排列種數沒有影響,因此僅需考慮在原佇列中的元素數目i和在棧中的元素數目j。若i為0,則待排元素的排列種數僅有一種,即將棧中的元素全部彈出。若i不為0,則dp i j dp i 1 j 1 從原...
洛谷P1155 雙棧排序
tom最近在研究乙個有趣的排序問題。如圖所示,通過2個棧s1和s2,tom希望借助以下4種操作實現將輸入序列公升序排序。操作a如果輸入序列不為空,將第乙個元素壓入棧s1 操作b如果棧s1不為空,將s1棧頂元素彈出至輸出序列 操作c如果輸入序列不為空,將第乙個元素壓入棧s2 操作d如果棧s2不為空,將...