洛谷P1145 约瑟夫

题目描述

n个人站成一圈,从某个人开始数数,每次数到m的人就被杀掉,然后下一个人重新开始数,直到最后只剩一个人。现在有一圈人,k个好人站在一起,k个坏人站在一起。从第一个好人开始数数。你要确定一个最小的m,使得在第一个好人被杀死前,k个坏人先被杀死。

感谢yh大神指出样例数据的错误。

输入输出格式

输入格式:

一个k,0<k<14

输出格式:

一个m

输入输出样例

输入样例#1:
3
输出样例#1:
5
输入样例#2:
4
输出样例#2:
30

说明

0<k<14

分析:正解就是暴力.只要稍微优美那么一点点就能过了,最最最朴素的暴力就是枚举m,然后一位一位地挪,非常慢,正确的方法是直接取模,判断是不是坏人,每一个m最多走k次就会结束游戏,每次删除一个人后把起点变一下,模数变一下就好了.需要注意的一点是每个人的下标要从0开始,不然取模的时候可能会得到0,然后就炸了.

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

int k,m = 1,beginn = 1;
bool flag = false,flag2 = false;

bool check(int mod)
{
    int t = (beginn + m - 1) % mod;
    if (t >= k)
    {
        beginn = t;
        return true;
     } 
     return false;
}

int main()
{
    scanf("%d",&k);
    m = k;
    while (1)
    {
        beginn = 0;
        flag2 = 0;
        for (int i = 0; i < k; i++)
        {
            if (!check(2 * k - i))
            {
                flag2 = 1;
                break;
            }
        }
        if (!flag2)
        break;
        m++;
    }
    printf("%d
",m);
    
    return 0;
}
原文地址:https://www.cnblogs.com/zbtrs/p/7465075.html