【Luogu P1965】[NOIP2013 提高组] 转圈游戏

链接

luogu P1965

题目描述

有一游戏,规则如下:围圆圈坐,座位编号从0到 n - 1,现有若干轮游戏
每一轮第 0 号位置上的同学顺时针走到第 m 号位置
第1号位置同学走到第 m+1 号位置…
现在,一共进行了 10^k 轮,请问 x 号同学最后走到了第几号位置。

样例输入

10 3 4 5

样例输出

5

思路

我比较菜,没想到公式,还是用的很朴素的想法:
枚举从x出发,经过r轮之后重新回到了x点,然后快速幂求出 1 0 k   %   r 10^k\ \%\ r 10k % r,最后的余数再手动跑掉就可以了
大佬公式: ( x % n + m % n ∗ 1 0 k % n ) (x\%n+m\%n*10^k\%n)%n (x%n+m%n10k%n)

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#define ll long long

int n, m, k, x;
ll kk, r, t, b[1000005][5]; 

using namespace std;

ll ksm(int a, int b)
{
    
    
	int p = 1;
	while(b)
	{
    
    
		if(b & 1) p = (p * a) % r;
		a = (a * a) % r;
		b /= 2;
	}
	return p;
}

int main()
{
    
    
//	freopen("game.in", "r", stdin);
//	freopen("game.out", "w", stdout);
	scanf("%d%d%d%d", &n, &m, &k, &x);
	int xx = x; 
	t = 0;
	while(!b[x][0])
	{
    
    
		xx = (xx + m) % n;
		if(xx == x) {
    
    t++; break;}
		if(!b[xx][0]) {
    
    
			b[xx][0] = 1;
			b[xx][1] = ++t;
		}
	}
	r = t - b[x][1];
	kk = ksm(10, k);
	if(!kk) printf("%d", x);
	else {
    
    
		for(int i = 1; i <= kk; ++i)
			x = (m + x) % n;
		printf("%d", x);
	}
	return 0;
	fclose(stdin);
	fclose(stdout);
}

猜你喜欢

转载自blog.csdn.net/LTH060226/article/details/115029133