游戏问题 / 转圈游戏
题目链接:luogu P1965 / SSL 2641 / SSL 2265
题目大意
有一个圈,人们按编号顺时针围着,每次人们会移动。
移动方法是每个人按顺时针方向走 m 步(m 给出)。
问你在走 10 的 k 次方次之后,原来在 x 位置的人现在在哪里。
多组询问。
思路
很明显,答案就是这个: ( x + 1 0 k × m ) m o d n (x+10^k\times m)\mod n (x+10k×m)modn
我是先跑出会循环节,然后再判定最后走到循环节的哪个地方,把它输出就可以了。
因为有次方,我们可以用快速幂来加速一下。
代码
#include<cstdio>
#define ll long long
using namespace std;
ll n, m, k, x;
ll q[1000001], zq;
ll read() {
ll re = 0, zf = 1;
char c = getchar();
while (c < '0' || c > '9') {
if (c == '-') zf = -zf;
c = getchar();
}
while (c >= '0' && c <= '9') {
re = (re << 3) + (re << 1) + c - '0';
c = getchar();
}
return re * zf;
}
void write(ll now) {
if (now < 0) {
printf("-");
write(-now);
return ;
}
if (now > 9ll) write(now / 10);
putchar(now % 10 + '0');
}
ll ksm(ll X, ll y) {//快速幂
ll re = 1ll;
while (y) {
if (y & 1) re = (re * X) % zq;
X = (X * X) % zq;
y >>= 1;
}
return re % zq;
}
int main() {
// freopen("game.in", "r", stdin);
// freopen("game.out", "w", stdout);
n = read();
m = read();
k = read();
x = read();
int now = x;
q[zq++] = now;
while ((now + m) % n != x) {
now = (now + m) % n;
q[zq++] = now;
}
k = ksm(10ll, k);
write(q[k]);
fclose(stdin);
fclose(stdout);
return 0;
}