题目大意:给出一个约瑟夫环,从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;
}