1. 程式人生 > >2018年全國多校算法寒假訓練營練習比賽(第一場)D N階漢諾塔變形

2018年全國多校算法寒假訓練營練習比賽(第一場)D N階漢諾塔變形

img 算法 cout ear www. sync 練習 style http

https://www.nowcoder.com/acm/contest/67/D

思路:

先手動模擬一下過程,以下是模擬過程,按順序表示第幾步需要移動的盤標號

1 1 2 1 1 2

1 1 3 1 1 2

1 1 2 1 1 3

1 1 2 1 1 2

1 1 4 1 1 2

。。。。。。

我們發現每出現兩次1就會出現一次2,每兩次2就會出現一次3,每兩次3就會出現一次4,每兩次4就會出現一次5。。。。。。

然後我們發現如果把所有大於1的標號看成1,那麽k步1出現的次數是 k/1

      如果把所有大於2的標號看成2,那麽k步2出現的次數是 k/3  

      如果把所有大於3的標號看成3,那麽k步3出現的次數是 k/3^2

      如果把所有大於4的標號看成4,那麽k步4出現的次數是 k/3^3  

      。。。。。。

那麽為什麽可以這樣呢

技術分享圖片

因為這樣我們就可以把移動的循環看成6步,剛才說過每出現兩次i,出現一下i+1,所以每移動兩步停一下(如圖③和⑥過程),所以k/3^(i-1)可以表示通過這個循環的步數,取余6就知道i走到哪裏了

代碼:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pb push_back
vector<int>a[3];
int main(){
    ios::sync_with_stdio(
false); cin.tie(0); ll n,k; while(cin>>n>>k){ for(int i=0;i<3;i++)a[i].clear(); ll base=1; for(int i=1;i<=n;i++){ int t=(k/base)%6; if(t>2)t=5-t; a[t].pb(i); base*=3; } for
(int i=0;i<3;i++){ if(a[i].size()) for(int j=a[i].size()-1;j>=0;j--)cout<<a[i][j]<<(j==0?\n: ); else cout<<0<<endl; } } return 0; }

2018年全國多校算法寒假訓練營練習比賽(第一場)D N階漢諾塔變形