您的位置:首页 > 编程语言

NOIP2013提高组复赛 转圈游戏 解题报告

2015-08-11 16:44 387 查看


描述

n 个小伙伴(编号从 0 到 n-1)围坐一圈玩游戏。按照顺时针方向给 n 个位置编号,从0 到 n-1。最初,第 0 号小伙伴在第 0 号位置,第 1 号小伙伴在第 1 号位置,……,依此类推。
游戏规则如下:每一轮第 0 号位置上的小伙伴顺时针走到第 m 号位置,第 1 号位置小伙伴走到第 m+1 号位置,……,依此类推,第n − m号位置上的小伙伴走到第 0 号位置,第n-m+1 号位置上的小伙伴走到第 1 号位置,……,第 n-1 号位置上的小伙伴顺时针走到第m-1 号位置。
现在,一共进行了 10^k 轮,请问 x 号小伙伴最后走到了第几号位置。


格式

输入格式

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

输出格式

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


样例1

样例输入1[复制]

10 3 4 5


样例输出1[复制]

5



限制

每个测试点1s。


提示

对于 30%的数据,0 < k < 7; 

对于 80%的数据,0 < k < 10^7; 

对于 100%的数据,1 < n < 1,000,000,0 < m < n,1 <= x <=n,0 < k < 10^9。


来源

NOIP 2013 提高组 Day 1

 

简单分析:
 



显然有环(即转圈的情况),即相当于从出发点直接走a个点,a:=(m*10^k) mod n【10^k这样输入是错误的】;

而题目数据太大,使用普通方法时间无法通过(我试了一下,能过百分之30左右)

所以想到优化10^k时的运算,即快速幂



 

 

 

代码如下:program circle;

var

n,m,x,dx:longint;

k:longint;

function kuaisumi(a,b,p:longint):longint;{快速幂}

var
  
快速幂,核心操作就是转化二进制

 
t,r:longint;

begin

r:=1;

t:=a;

while b>0 do

begin

if (b and 1)=1 then r:=r*t mod p; {也就是取b的二进制最末位}

t:=t*t mod p;

b:=b shr 1; {也就是去掉b的二进制最末位}

end;

exit(r);

end;

begin

assign(input,'write.in');

reset(input);

assign(output,'write.out');

rewrite(output);

readln(n,m,k,x);

dx:=kuaisumi(10,k,n);

dx:=(dx*m mod n+x) mod n;(化简圈数)

writeln(dx);

close(input);

close(output);

end.

更短的代码(方法相同)

program circle;

var a,n,y,k,m,x:longint;

begin

 readln(n,m,k,x);

 a:=m; y:=10;

 while k<>0 do

  begin

  if k and 1=1

  then a:=(a*y) mod n;

  y:=y*y mod n;

  k:=k shr 1;

  end;

 write((a+x)mod n);

end.



 

简单分析:


 

显然有环(即转圈的情况),即相当于从出发点直接走a个点,a:=(m*10^k) mod n【10^k这样输入是错误的】;

而题目数据太大,使用普通方法时间无法通过(我试了一下,能过百分之30左右)

所以想到优化10^k时的运算,即快速幂



 

 

代码如下:program circle;

var

n,m,x,dx:longint;

k:longint;

function kuaisumi(a,b,p:longint):longint;{快速幂}

var
快速幂,核心操作就是转化二进制

 
t,r:longint;

begin

r:=1;

t:=a;

while b>0 do

begin

if (b and 1)=1 then r:=r*t mod p; {也就是取b的二进制最末位}

t:=t*t mod p;

b:=b shr 1; {也就是去掉b的二进制最末位}

end;

exit(r);

end;

begin

assign(input,'write.in');

reset(input);

assign(output,'write.out');

rewrite(output);

readln(n,m,k,x);

dx:=kuaisumi(10,k,n);

dx:=(dx*m mod n+x) mod n;(化简圈数)

writeln(dx);

close(input);

close(output);

end.

更短的代码(方法相同)

program circle;

var a,n,y,k,m,x:longint;

begin

 readln(n,m,k,x);

 a:=m; y:=10;

 while k<>0 do

  begin

  if k and 1=1

  then a:=(a*y) mod n;

  y:=y*y mod n;

  k:=k shr 1;

  end;

 write((a+x)mod n);

end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  NOIP 2013 pascal 编程