SDNU 1300.转圈游戏 快速幂 找循环节

来源:互联网 发布:淘宝智能版现在免费吗 编辑:程序博客网 时间:2024/04/29 08:49

1300.转圈游戏

Description

 n个MM(编号从0到n-1)围在一圈“丢手绢”。按照顺时针方向给n个位置编号,从0到n-1。最初,第0号MM在第0号位置,第1号MM在第1号位置,……,依此类推。 

游戏规则如下:每一轮第0号位置上的MM顺时针走到第m号位置,第1号位置MM走到第m+1号位置,……,依此类推,第n−m号位置上的MM走到第0号位置,第n-m+1号位置上的MM走到第1号位置,……,第n-1号位置上的MM顺时针走到第m-1号位置。  现在,一共进行了10^k轮,请问x号MM最后走到了第几号位置。  

Input

输入共1行,包含4个整数n、m、k、x,每两个整数之间用一个空格隔开。 

Output

输出共1行,包含1个整数,表示10^k轮后x号MM所在的位置编号。  

Sample Input

10 3 4 5

Sample Output

5


    题意中文不用多说,看完题第一反应想到了约瑟夫环,不过这个跑的环数是10^k,所以肯定不能一个一个跑啦= =围成一圈走的话次数多了肯定就能构成一个规律,找出循环节再用快速幂的方法就可以得出结果了。

    下面AC代码

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;int f[1000005];int repetend(int m,int n){     int i,j;     int k;     f[0]=0;     f[1]=(f[0]+m)%n;     f[2]=(f[1]+m)%n;     //cout<<"第1节是 "<<f[0]<<endl;     //cout<<"第2节是 "<<f[1]<<endl;     //cout<<"第3节是 "<<f[2]<<endl;     for(i=3;i<1000000;i++)     {          f[i]=(f[i-1]+m)%n;          //cout<<"第"<<i+1<<"节是 "<<f[i]<<endl;          if(f[i-1]==f[0]&&f[i]==f[1])          {               k=i-1;               break;          }     }     return k;}int counting(int a,int b,int c){     int ans;     ans=1;     a=a%c;     while(b>0)     {          if(b%2==1)          {               ans=(ans*a)%c;          }          b=b/2;          a=(a*a)%c;     }     return ans;}int main(){     int n,m,k,x;     int rep;     int t;     while(scanf("%d%d%d%d",&n,&m,&k,&x)!=EOF)     {          rep=repetend(m,n);          //cout<<"循环节为 "<<rep<<endl;          t=counting(10,k,rep);          //cout<<"走到了第"<<t<<"节"<<endl;          cout<<(f[t]+x)%n<<endl;     }     return 0;}


0 0