HDU 1210 Eddy's 洗牌问题

来源:互联网 发布:2016好声音网络直播 编辑:程序博客网 时间:2024/05/29 11:23

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1210  

题目:

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::

20

1

output:

20

2

解题思路:

 先举个例子:n=3;即初始状态为:1,2,3    4,5,6,;

第一次:4,1,5      2,6,3;

第二次:2,4,6      1,3,5;

第三次:1,2,3      4,5,6;  

因此可以将2*n张牌分成两个部分。我们只要判断第一张牌(即1)所在的位置就能判断下次洗牌之后能不能达到原来的状态;令第一张牌的位置为s1(表示在第一部分),s2(表示在第二部分);洗牌次数为k;

洗牌一次 k++;

当在第一部分时:洗牌后的位置:x=2*s1;  如果x>n则说明洗牌之后在第二部分,即s2=x-n;

当在第二部分时,洗牌后的位置:x=2*(s2-1)+1;如果x>n.则说明仍在第二部分,即s2=x-n;如果x<=n,则说明洗牌后在第一部分,即:s1=x;

洗牌之后,如果在第二部分且x=1;则说明下次洗牌能达到初始状态;则洗牌的次数即为k+1;


转载请注明出处:http://blog.csdn.net/yhrun

#include<iostream>#include<algorithm>#include<cstring>using namespace std;int main(){int n;while(cin>>n){int flat=1;int k=1;int s=0;   //flat为标记第一张牌的位置,flat=1表示在第一部分,flat=0表示在第二部分。s表示洗牌次数while(1){s++;if(flat)               //第一张牌在第一部分{k=2*k;if(k>n){k-=n;flat=0;if(k==1)break;   //处在第二部分,且k==1,则下次洗牌一定能达到初始状态}}else                      //第一张牌在第二部分{k=2*(k-1)+1;if(k<=n){flat=1;}else{ k-=n;if(k==1)break;   //处在第二部分,且k==1,则下次洗牌一定能达到初始状态}}}cout<<s+1<<endl;}}