UVALive - 4727 Jump 约瑟夫环

来源:互联网 发布:mt4 画线下单源码 编辑:程序博客网 时间:2024/06/05 00:07

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


0 0
原创粉丝点击