題目描述
2060年是云南中醫學院的百年校慶,于是學生會的同學們搞了一個連續猜謎活動:共有10個謎題,現在告訴所有人第一個謎題,每個謎題的答案就是下一個謎題的線索....成功破解最后一個謎題后,答案就是指向獎勵的線索
在所有同學們的努力下,全校同學們獲得了最后一個謎題,這個謎題有幾十張紙,上面全是密密麻麻的數字以及'.'
第一頁內容如下:
1,2,3,4,5,6
4,1,5,2,6,3
2,4,6,1,3,5
1,2,3,4,5,6
———3
1,2,3,4....32
.............
.............
———10
有細心的同學發現,這是對一組1-2n的序列進行如下移動:每次將前n個數字取出,按順序依次插入到位于n+1,n+2...2n的數字后面,最后的數字表示多少次移動后會變回原來的序列
第二頁內容如下:
1,2,3,4....64
.............
.............
———?
1,2,3,4....140
.............
.............
———?
同學們發現,越往后翻,這個序列的長度就越長,前面十幾二十個數字的序列同學們還可以一步一步模擬做出來,但是到后來幾千甚至上萬的長度,就沒有辦法計算了,甚至中間一步做錯,就步步都錯。
這個謎題真是太過分了!但是獎勵就在眼前,只要計算出所有答案,所有答案就是指引同學們獲得獎勵的線索,那么現在問題來了,同學們除了發現上面的n=最后那個數字/2之外,沒有辦法給你任何幫助,而作為一個計算機科學與技術專業的大佬,你自然就成為了同學們心目中拯救他們的英雄,所以你能不能寫一個程序,當你知道n是多少的時候,可以直接得出答案呢?
?
輸入
多組測試數據.每組數據的第一行包含一個正整數n(1<= n<=10000).
?
輸出
每組數據輸出一行整數表示最少需要經過幾次移動能變回原序列,若不能,則輸出"-1"
?
樣例輸入
復制樣例數據
3 16
樣例輸出
3 10
解決思路:
通過將前幾種情況,可以將一些規律大致推導出來,我們可以根據1所在的位置判斷出還需要進行幾步到達第一位,當1恢復原位后,會發現其他數也恢復原位,因此可以知道在經過num步后,當1到達n+1位置時,則還需要1步恢復原位,當1到達n*2時,還需要num步恢復原位,對于其他的情況,則根據它所處的位置,假如1當前的位置時x,當n<x<=2*n時,下一步到達(x-n)*2-1,若1<=x<=n時,下一步到達x*2位,并標記經過的位置,若走到已走過的位置,則證明無法實現,輸出-1(ps:這題好像并不會出現這種情況)
代碼:
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <map>
#include <stack>
#include <queue>
#include <vector>
#include <bitset>
#include <set>
#include <utility>
#include <sstream>
#include <iomanip>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define inf 0x3f3f3f3f
#define rep(i,l,r) for(int i=l;i<=r;i++)
#define lep(i,l,r) for(int i=l;i>=r;i--)
#define ms(arr) memset(arr,0,sizeof(arr))
//priority_queue<int,vector<int> ,greater<int> >q;
const int maxn = (int)1e5 + 5;
const ll mod = 1e9+7;
bool vis[22000];
int main()
{#ifndef ONLINE_JUDGEfreopen("in.txt", "r", stdin);#endif//freopen("out.txt", "w", stdout);ios::sync_with_stdio(0),cin.tie(0);int n;while(scanf("%d",&n)!=EOF) {fill(vis+1,vis+1+2*n,false);int t=1;int num=0;for(int k=0;;k++) {t=t+(1<<k);if(t>2*n) {t=t-(1<<k);break;}num++;vis[t]=true;}if(t==n+1) printf("%d\n",num+1);else if(t==n*2) printf("%d\n",num*2);else {int nape=t;while(1) {if(nape>n) {nape=(nape-n)*2-1;num++;if(nape==n+1) {printf("%d\n",num+1);break;}if(nape==1) {printf("%d\n",num);break;}if(nape==n*2) {printf("%d\n",num*2);break;}if(vis[nape]==true) {printf("-1\n");break;}else {vis[nape]=true;continue;}}else {nape=nape*2;num++;if(nape==n+1) {printf("%d\n",num+1);break;}if(nape==1) {printf("%d\n",num);break;}if(nape==n*2) {printf("%d\n",num*2);break;}if(vis[nape]==true) {printf("-1\n");break;}else {vis[nape]=true;continue;}}}}}return 0;
}
?