2641 2016东莞市特长生考试 游戏问题

  • 题目
  • 题解
  • 代码

题目

“五四”青年节到了,某学校要举行一个游园活动,其中有一个这样的游戏: 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< n<1,100,000;0< m< n;1< =x<=n;0< k<10^9

题解

用快速幂一边求一边mod n
(ksm)快速幂为一个快速求幂的算法
很容易想到,其实比如说算2^4的时候当算到2^2时只要平方一下就好了,不用再算2^3的值是多少。下面的快速幂的方法就要用到这一点,利用二进制的方法减小复杂度。

用临时变量tmp记录现在算到的幂(即上文说到2^2)大体思路是这样的,我们只在二进制位为1的位做一次,返回值变量(ret)乘以tmp。

时间复杂度(log k)

代码

var
  n,m,k,x:longint;

function ksm(a,b:longint):longint;//a的b次幂
var
  x,y:int64;
begin
  x:=1;//最终值
  y:=a;//底数
  while b>0 do
    begin
      if (b and 1)=1 then x:=x*y mod n;
      //当二进制末尾为1时更新x
      y:=y*y mod n;
      b:=b shr 1;//相当于b=b div 2
    end;
  exit(x);
end;

begin
  readln(n,m,k,x);
  writeln(((ksm(10,k)*m mod n)+x) mod n);
end.
#include 

using namespace std;

long long n,m,k,x;

long long ksm(long long a,long long b)
{
    long long x,y;
    x=1;
    y=a;
    while (b>0)
    {
        if ((b&1)==1) x=(x*y)%n;
        y=(y*y)%n;
        b=b>>1;
    }
    return(x);
}

int main()
{
    scanf("%lld%lld%lld%lld",&n,&m,&k,&x);
    printf("%lld",(((ksm(10,k)*m)%n)+x)%n);
}

你可能感兴趣的:(快速幂)