Josephus again HDU - 3089 (约瑟夫环问题)

In our Jesephus game, we start with n people numbered 1 to n around a circle, and we eliminated every k remaining person until only one survives. For example, here’s the starting configuration for n = 10, k = 2, The elimination order is 2, 4, 6, 8, 10, 3, 7, 1, 9. So 5 survives.The problem: determine the survivor’s number , J(n, k).
Input
There are multiple cases, end with EOF
each case have two integer, n, k. (1<= n <= 10^12, 1 <= k <= 1000)
Output
each case a line J(n, k)
Sample Input
10 2
10 3
Sample Output
5
4
问题显而易见,对于这种问题,我们是有递推公式的;
假设 f(n) 的定义为从0到 n1 标号的人中,最后留下的那个人的编号,且是数到第 m1 (从第0个开始数)个离开
有递推公式:

f(n)=(f(n1)+m)%n

所以答案就是 f(n)+1
但是这里的n非常大,线性递推是不可行的,所以我们得优化一下递推过程。

我们看一下递推是,如果 (f(n1)+m) 远远小于n,那么实际上可以看成没有经过取余,而是一直累加 m ,直到(f(n1)+m)>n,设 f(n1) num
我们分:

num+m>=n
num+m<n

讨论,如果是第一种只要正常递推即可,第二种,我们只要看他可以累加到多少个m。
设可以累加x个m,即满足
num+xm<i+x1
,这里x至少会取到1,因为这第二种情况讨论的条件
所以:
x=inum1m1(x1)

若此时 (i+x1)>n ,那么 num+m(n+1i) 就是答案

#include<iostream>
#include<cstdio>
using namespace std;
int f[100000];
long long solve(long long n,long long m)
{
    long long i=2;
    long long num=0;
    for(;;)
    {
        if(i>n)
            break;
        if(num+m>=i)
        {
            num=(num+m)%i;
            i++;
        }
        else
        {
            long long x=(i-num-1)/(m-1);
            if((i-num-1)%(m-1)==0)
                x--;
            if(i+x-1>n)
            {
                return num+(n+1-i)*m+1; //这里得出答案和实际都差1,所以需要在加1
            }
            else
            {
                num+=x*m;
                i+=x;
            }
        }
    } 
    return num+1;
}
int main()
{
    long long n,m; 
    while(scanf("%lld%lld",&n,&m)==2)
    {
        if(m==1)
            printf("%lld\n",n);
        else
            printf("%lld\n",solve(n,m));
    }

    return 0;
}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值