UVALive - 4727 Jump 约瑟夫环

本文介绍了一种高效解决约瑟夫环问题的方法,特别关注如何找到最后剩下的三个数。通过初始化不同起点并逐步递推,最终确定这三个数的具体位置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目大意:给出一个约瑟夫环,从1开始到n,现给出一个k,数到k表示要退出,现在要你求输出最后面的三个数

解题思路:这题有一个公式,具体就不在阐述了,可以百度以下:约瑟夫环的数学优化

这里讲一下如果求最后的三个数如何求,由递归公式得,首先要初始化f[i],然后再由f[i]往上递归到f[n],得到的这个f[n]表示的其实是倒数第i个数的值

也就是说如果要求倒数第一个数的值,就要初始化f[1],然后由1--n递归,最后的f[n]就是倒数第一个数的值了,依此类推,求倒数第二个和倒数第三个,只需要初始化f[2]和f[3]即可

关键是f[2]和f[3]是多少,这里说一下f[2],因为只剩下两人,从0开始编号,从0开始报数,现在只要知道出去的那个人是谁,就知道倒数第二个人的值了,可以得出去的那个人是(k  + 1)% 2,倒数第三个人也可以推得出来,如果推不出来,表示对约瑟夫的理解不够深,多去看看就懂了

#include<cstdio>
#include<cstring>
using namespace std;
#define maxn 500010
int f[maxn];

int main() {
	int test, n, k;
	scanf("%d",&test);
	while(test--) {
		scanf("%d%d",&n, &k);
		f[1] = 0;
		for(int i = 2; i <= n; i++)
			f[i] = (f[i-1] + k) % i;
		int ans1 = f[n];
		f[2] = (k - 1) % 2;
		for(int i = 3; i <= n; i++)
			f[i] = (f[i-1] + k) % i;
		int ans2 = f[n];
		f[3] = (k - 1) % 3;
		for(int i = 4; i <= n; i++)
			f[i] = (f[i-1] + k) % i;
		int ans3 = f[n];
		printf("%d %d %d\n",ans3+1, ans2+1, ans1+1);
	}
		return 0;
	}


#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 500010
int n, k;
int f[maxn];

int solve(int m) {
	f[m] = (k - 1) % m;
	for(int i = m + 1; i <= n; i++)
		f[i] = (f[i - 1] + k) % i;
	return f[n] + 1;
}

int main() {
	int test;
	scanf("%d", &test);
	while(test--) {
		scanf("%d%d", &n, &k);
		printf("%d %d %d\n", solve(3), solve(2), solve(1));
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值