UVA-3882(递推)

UVA

题意:约瑟夫环。给定n,k,m,人从1排到n,从1报数,第一次先杀报到m的人,之后杀报到k的人。

思路:先看经典的约瑟夫问题。n个人,从0号到n-1号围坐成一个圈。从0报数报到k-1的人死。之后第k人继续从0开始报数。如此直到只剩一人,则胜利。问胜利人的编号是多少。

 

第1轮:n-1人:0,1,2……k-2,k,k+1……n-2,n-1,第k-1人死。之后形成了一个n-1个人的新的约瑟夫环。

整理-:k,k+1……n-2,n-1,0,1,2……k-2。新的约瑟夫环。重新排序号得

n-1人:0,1,……n-2-k,n-1-k,n-k,n-k+1,n-k+2……n-2。

 

第2轮:……

……

 

假设第2轮排x的人,在第1轮排x',x'=(x+k)%n。由此我们得知n-1个人的编号对应的n人约瑟夫环的编号。

想要知道第n个人的编号,就要得到n-1人的编号,就要得到n-2的编号,……,最后的约瑟夫环中,只有一人。编号为0。所以递推到n人就知道胜利者的编号了。

 

回到此题。此题是第一次先杀m,之后在杀报道k的。那么就从1个人开始递推,递推到n-1人。之后最后一次递推是x'=(x+m)%n。这样得到的是0到n-1编号的人的胜利者。最后再把得到的编号加一就行了。

 1 #include <iostream>
 2 #include <cstdio>
 3 
 4 using namespace std;
 5 
 6 int n, k, m;
 7 
 8 int main()
 9 {
10     while(scanf("%d%d%d", &n, &k, &m), n+k+m){
11         int ans = 0;
12         for (int i = 2; i < n; i++){
13             ans = (ans+k)%i;
14         }
15         ans = (ans+m)%n;
16         printf("%d\n", ans+1);
17     }
18     return 0;
19 }

 

posted @ 2016-02-24 13:21  喷水小火龙  阅读(138)  评论(0)    收藏  举报