1. 程式人生 > >[DP][高精][NOIP]Hanoi雙塔問題

[DP][高精][NOIP]Hanoi雙塔問題

遞推 裏的 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雙塔問題