zoukankan      html  css  js  c++  java
  • 约瑟夫问题

    问题描述

    现有N(N+1)/2 个人围成一圈,编号从1到N(N+1)/2,其中编号i与编号i+1的人相邻,编号N*(N+1)/2与编号1相邻。如今,我们要执行N-1个阶段的杀人仪式,在第一个阶段开始前,从编号为1的人开始报数。在第i阶段中,报到n+1-i这个数的人要被杀害,之后从被杀害者的下一个相邻的人开始从1开始报数,在第i个阶段里需要杀死i个人,随后即可进入下一个阶段,更具体地说:
    在第1个阶段中,报数为N的人会被杀害,在这个阶段中需要杀死N个人;
    在第2个阶段中,报数为N-1的人会被杀害,在这个阶段中需要杀死N-1个人;
    ……
    在第n-1个阶段中,报数为2的人会被杀害,在这个阶段中需要杀死2个人。

    仪式结束后,会剩下一个幸存者,请问这位幸存者的编号是多少?

    输入格式

    第一行一个整数T,表示数据的组数。
    接下来T行,每行一个整数N,N定义如题目所述。
    

    输出格式

    输出一个整数,表示幸存者的编号

    输入样例:

    3
    1
    2
    3
    

    输出样例:

    1
    3
    2
    

    数据范围

    20%数据,1<=n<=100,T <=10
    40%数据,1<=n<=100,000,T<=10
    100%数据,1<=n<=5,000,000,T<=100000

    代码

    #pragma GCC optimize(1)
    #pragma GCC optimize(2)
    #pragma GCC optimize(3)
    #pragma GCC optimize("Ofast")
    #pragma GCC optimize("inline")
    #include <bits/stdc++.h>
    using namespace std;
    const int N=5e6+7;
    const int T=1e6+6;
    int n,a[T];
    long long f[N];
    inline int read() {//fastread
        int x = 0,f = 1;
        char ch = getchar();
        while(ch < '0' || ch > '9') {
            if(ch == '-')
                f = -1;
            ch = getchar();
        }
        while(ch >= '0' && ch <= '9') {
            x = (x << 1) + (x << 3) + (ch ^ 48);
            ch = getchar();
        }
        return x * f;
    }
    long long odd(long long n, long long size, long long v)
    {
        long long last, advan, a, b;
        last = (n-1) * (n+1) / 2;
        if(last + v < size)
            return last + v;
        v -= size - last - 1;
        for (last=v; ; last=advan+v)
        {
            a = last /n, b = last / (n+1);
            advan = a+b;
            if(advan+v == last)
                break;
        }
        return last;
    }
    
    long long even(long long n,long long size,long long v)
    {
        long long last, advan, a, b, s=n/2;
        last = n * n / 2;
        if(last+v <= size)
            return last+v;
        v -= size - last;
        for(last=v; ; last=advan+v)
        {
            a=last/n,b=a;
            if(last>=(b+1)*n-(s-b))++b;
            advan = a + b;
            if(advan+v==last)
                break;
        }
        return last;
    }
    
    int main()
    {
        freopen("josephus.in", "r", stdin);
        freopen("josephus.out", "w", stdout);
        scanf("%d",&n);
        for(int i=1; i<=n; i++) scanf("%d",&a[i]),a[0]=max(a[0],a[i]);
        f[1]=1;
        for(long long i=2; i<=a[0]; i++)
        {
            if(i&1) 
                f[i]=odd(i,i*(i+1)/2,f[i-1]);
            else 
                f[i]=even(i,i*(i+1)/2,f[i-1]);
        }
        for(int i=1; i<=n; i++) cout<<f[a[i]]<<endl;
        return 0;
    }
    
  • 相关阅读:
    七、python抽象
    六、python条件、循环及其它语句
    泛型数组
    判断数组是否包含此元素
    数组倒序
    Class字节码文件获取的三种方法
    操作系统的产生
    Java重载的概述
    表设计遵循的三大范式实例
    pyqt5窗体分隔
  • 原文地址:https://www.cnblogs.com/LJA001162/p/13462886.html
Copyright © 2011-2022 走看看