爲了表彰小聯爲Samuel星球的探險所作出的貢獻,小聯被邀請參加Samuel星球近距離載人探險活動。 因爲Samuel星球至關遙遠,科學家們要在飛船中度過至關長的一段時間,小聯提議用撲克牌打發長途旅行中的無聊時間。玩了幾局以後,你們以爲單純玩撲克牌對於像他們這樣的高智商人才來講太簡單了。有人提出了撲克牌的一種新的玩法。html
對於撲克牌的一次洗牌是這樣定義的,將一疊N(N爲偶數)張撲克牌平均分紅上下兩疊,取下面一疊的第一張做爲新的一疊的第一張,而後取上面一疊的第一張做爲新的一疊的第二張,再取下面一疊的第二張做爲新的一疊的第三張……如此交替直到全部的牌取完。 若是對一疊6張的撲克牌1 2 3 4 5 6,進行一次洗牌的過程以下圖所示:c++
從圖中能夠看出通過一次洗牌,序列1 2 3 4 5 6變爲4 1 5 2 6 3。固然,再對獲得的序列進行一次洗牌,又會變爲2 4 6 1 3 5。 遊戲是這樣的,若是給定長度爲N的一疊撲克牌,而且牌面大小從1開始連續增長到N(不考慮花色),對這樣的一疊撲克牌,進行M次洗牌。最早說出通過洗牌後的撲克牌序列中第L張撲克牌的牌面大小是多少的科學家得勝。小聯想贏取遊戲的勝利,你能幫助他嗎?web
有三個用空格間隔的整數,分別表示N,M,L (其中0< N ≤ 10 ^ 10 ,0 ≤ M ≤ 10 ^ 10,且N爲偶數)。spa
單行輸出指定的撲克牌的牌面大小code
6 2 3
6
咱們先手動模擬一下這副牌(以8爲例):htm
咱們每次洗牌,又把牌分紅兩部分,咱們來找找規律(設一張牌的位置爲x)blog
前一部分牌,下一次都會到2*x的位置遊戲
後一部分牌,下一次都會到(x-n/2)*2-1的位置ci
由於他給咱們的是洗完m次牌後的位置l,因此咱們只需倒推便可it
可是怎麼知道當前這張牌是由那一部分推過來的呢?
再回頭看看規律,你就知道,從前一部分洗來的牌都是偶數位置,後一部分洗來的牌都是奇數位置,因此只要判斷當前位置的奇偶性遞推就好了,可是看看數據大小,確定要超時啊,但他洗牌不管洗多少次,總有一個循環節,咱們求出循環節的長度,m對長度取模輸出,就不用去模擬了。
1 #include<bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 ll n,m,l; 5 ll flag[10000001];//記錄循環節中第i次洗牌後的位置ai 6 ll ans=1; 7 int main() 8 { 9 cin>>n>>m>>l; 10 flag[0]=l; 11 while(1) 12 { 13 if(l%2==0)//從前半部分推來的 14 { 15 l/=2; 16 } 17 else//後半部分 18 { 19 l=(l+1)/2+n/2; 20 } 21 if(l==flag[0])break;//重複了,循環節就找完了 22 flag[ans]=l; 23 ans++; 24 } 25 m%=ans;//取模 26 cout<<flag[m]<<endl; 27 //輸出洗完m次牌後當前位置的數 (由於從有序開始洗的牌,因此位置就是牌的編號) 28 }