[DP][高精][NOIP]Hanoi雙塔問題
阿新 • • 發佈:2017-08-04
遞推 裏的 stream pre 圓盤 algo 公式推導 noi void
題目梗概
Hanoi塔問題的基礎上,每種圓盤加了一個。實際內容並沒有變化。
思考
首先來一波Hanoi問題的步數公式推導:
首先n個不同的圓盤。
只有把n-1個圓盤從a->b,最後把a上剩余的一個圓盤從a->c。
之後把b上的n-1個圓盤從b->c。
這裏的兩步:把n-1個圓盤從a->c,和n-1個圓盤從b->c.所需要的步驟數。實際上就是把n-1個圓盤從a移動到c的步驟數*2,因為是等價的。從a->b和從b->c移動的圓盤個數都是一樣的,所以步數就是 (n-1)*2。
然後還要多一步就是把a上的一個圓盤放到c。
所以遞推式是 $A_{n}=A_{n-1}\times 2+1$
這個遞推式一般遞推取模時使用,不過有個更加簡便的公式。
$A_{n}=A_{n-1}\times 2+1$
$\mapsto A_{n} = A_{n-1}\times 2 + 1 + 1 - 1$
$\mapsto A_{n} = A_{n-1}\times 2 + 2 - 1$
$\mapsto A_{n} + 1 = (A_{n-1} + 1 )\times 2$
設$B_{n}=A_{n}+1$
則$B_{n}$為等比數列
所以$B_{n}=B_{1}\times 2^{n-1}$ 即 $B_{n}=2 \times 2^{n-1}$ -> $B_{n}=2^{n}$
所以$A_{n}=2^{n}-1$
推導完畢
這道題目不過是兩個相同的圓盤,所以只是步數*2的問題。只不過這道題目需要高精
代碼實現:
#include <cstdio> #include <iostream> #include <algorithm> int Pos,a[1002],n,len=1; void Run(int n){ a[1]=1; while(n--){ for(int i=1;i<=len;i++){ a[i]*=2; }for(int i=1;i<=len;i++){ if(a[i]>9) { a[i+1]+=a[i]/10; a[i]%=10; } } if(a[len]) len++; } a[1]-=2; while(a[len]==0){ len--; } for(int i=len;i>=1;i--){ printf("%d",a[i]); } return ; } int main(){ scanf("%d",&n); Run(n+1); return 0; }
[DP][高精][NOIP]Hanoi雙塔問題