程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 杭電OJ——1210 Eddys 洗牌問題

杭電OJ——1210 Eddys 洗牌問題

編輯:C++入門知識

Eddy's 洗牌問題     Problem Description Eddy是個ACMer,他不僅喜歡做ACM題,而且對於紙牌也有一定的研究,他在無聊時研究發現,如果他有2N張牌,編號為1,2,3..n,n+1,..2n。這也是最初的牌的順序。通過一次洗牌可以把牌的序列變為n+1,1,n+2,2,n+3,3,n+4,4..2n,n。那麼可以證明,對於任意自然數N,都可以在經過M次洗牌後第一次重新得到初始的順序。編程對於小於100000的自然數N,求出M的值。     Input 每行一個整數N     Output 輸出與之對應的M     Sample Input 20 1     Sample Output 20 2     Author Eddy     Source 杭電ACM省賽集訓隊選拔賽之熱身賽     Recommend Eddy     關於這道題的做法,我這裡復制一下杭電的解題報告:   Eddy's洗牌   原始算法:   我們把每個數逛來逛去最後又回家的過程叫做一個循環,循環中經過的位置個數叫做循環的長度。如N=4時,有 兩個循環:1-2-4-8-7-5-1,長度為6;3-6-3,長度為2。答案就是所有循環長度的最小公倍數。顯然算法時空復雜度均為O(n)(因為需要記錄一個數是否已被某個循環經過)。   高效算法:   1所在的循環長度就是答案。時間復雜度小於O(n),空間復雜度為O(1),編程復雜度也遠低於原始算法。這個算法是建立在如下結論之上的:“1所在的循環長度是其它任一循環長度的倍數”,或者表述為“1回家時,其它任一數字也一定回了家”。   給出的證明:   題目中的移動規則,其實就是每次把在第x個位置的數移動到位置x*2 mod (2*n+1)。這個式子是十分巧妙的,請用心領悟。由這個式子可以得出任一數字x在p步之後的位置:x*2^p mod (2*n+1)。假設1經過p步回了家,那麼可得1*2^p mod (2*n+1)=1。由此可得對任一數字x,均有x*2^p mod (2*n+1)=x,即1回家時任一數字都回了家。    發代碼: [cpp]  #include<iostream>   using namespace std;      int main()   {       int num,i,p,sum;       while(cin>>num && num!=EOF)       {           p=2*num+1;           for(i=1,sum=1;;i++)           {                  sum=(sum*2)%p;               if(sum==1)                   break;           }           cout<<i<<endl;       }       return 0;   }    

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved