1. 程式人生 > >UVA - 1452 Jump (約瑟夫環變式)

UVA - 1452 Jump (約瑟夫環變式)

題目大意:

       給出n,m,約瑟夫環共n項,每數到m殺一個人,問剩下的倒數第3個人、倒數第2個人、倒數第1個人的編號分別是多少

題解:

       因為我們都知道求約瑟夫環問題是f[1]=0, f[n]=(f[n-1]+k)%i ,所以一開始我的想法是就用同樣的方法來推倒數第2個人,

f[2]=0,f[n]=(f[n-1]+k)%i ;但是得出的結果卻不對,

      在倒數第2局標號為1的不一定在本局出局,在m=2的情況下是這樣,被樣例誤導了........

      但是倒數第2局一定是隻有編號為0和1的兩個人,所以我們可以求出倒數第1個人在倒數第2局的標號,然後1-這個編號倒數第2個人在倒數第2局的編號,有了起始編號之後剩下的就是按照那個公式推了( f[n]=(f[n-1]+k)%i)

      同理,倒數第3個人在倒數第3局的編號,然後順著退就ok了。於是我們可以求出倒數第1個和倒數第2個人在倒數第3局的編號,它們和倒數第3個人的編號一定分別是0,1,2,所以ans3=(0^1^2)^ans1^ans2;

#include<bits/stdc++.h>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#define max_n 10010
typedef long long LL;
using namespace std;
int main()
{
    //freopen("input.txt","r",stdin);
    int n,k,T;
    scanf("%d",&T);
    int ans1=0,ans2=0,ans3=0;
    while(T--)
    {
        scanf("%d%d",&n,&k);
        ans1=0,ans2=0,ans3=0;
        for(int i=2;i<=n;++i)
        {
            ans1=(ans1+k)%i;
            if(i==2)
            {
                ans2=1-ans1;
                continue;
            }
            ans2=(ans2+k)%i;
            if(i==3)
            {
                ans3=(0^1^2)^ans1^ans2;
                continue;
            }
            ans3=(ans3+k)%i;
        }
        printf("%d %d %d\n",ans3+1,ans2+1,ans1+1);
    }

    return 0;
}