【题目链接】
ybt 1617:转圈游戏
ybt 1875:【13NOIP提高组】转圈游戏
洛谷 P1965 [NOIP2013 提高组] 转圈游戏
【题目考点】
1. 取模运算
【解题思路】
第x号小伙伴第一轮后走到 x + m x+m x+m位置,第二轮后走到 x + 2 m x+2m x+2m位置,如果该位置的值超过了n,位置编号要减n,使得位置编号只能在0~n-1范围内。因此 1 0 k 10^k 10k轮后,第x号小伙伴所在的位置为 ( x + 1 0 k ⋅ m ) % n (x+10^k\cdot m)\%n (x+10k⋅m)%n。
已知x、m都小于n。根据同余定理的乘法应用: a ⋅ b % m = ( a % m ⋅ b % m ) % m a\cdot b \% m = (a\%m \cdot b\%m)\%m a⋅b%m=(a%m⋅b%m)%m
有:
( x + 1 0 k ⋅ m ) % n (x+10^k\cdot m)\%n (x+10k⋅m)%n
= ( x % n + ( 1 0 k % n ⋅ m % n ) % n ) % n =(x\%n+(10^k\%n\cdot m\%n)\%n)\%n =(x%n+(10k%n⋅m%n)%n)%n
= ( x + ( 1 0 k % n ⋅ m ) % n ) % n =(x+(10^k\%n\cdot m)\%n)\%n =(x+(10k%n⋅m)%n)%n
主要问题是求 1 0 k % n 10^k\%n 10k%n
k达到 1 0 9 10^9 109,这里必须使用快速幂算法(快速幂算法求幂的复杂度为 O ( l o g n ) O(logn) O(logn),n是指数的大小)。
根据同余定理,有: a b % m = ( a % m ) b a^b\%m = (a\%m)^b ab%m=(a%m)b。在使用快速幂的过程中,对于底数a和结果r,每次运算后都对m取模即可。
【题解代码】
解法1:快速幂
#include<bits/stdc++.h>
using namespace std;
int fastPowMod(int a, int b, int m)//快速幂求a^b%m
{
int r = 1;//结果
while(b > 0)
{
if(b % 2 == 1)
r = (r * a) % m;
a = (a * a) % m;
b /= 2;
}
return r;
}
int main()
{
int n, m, k, x;
cin >> n >> m >> k >> x;
cout << (x + fastPowMod(10, k, n) * m % n) % n;
return 0;
}