HDU 1488(Flavius Josephus Reloaded)

由于士兵总数最多为 10^9,无法申请这么大的数组,又根据题目描述,最多选择 10^6 个士兵,就会进入循环(再次选择之前选择过的士兵),所以使用哈希链,用每个士兵的编号对 10^6 取余,余数相同的士兵放在同一个哈希链中。

#include <iostream>
#include <cstring>
using namespace std;
const int MAXL = 1000005;

struct soldier //士兵
{
    int number; //编号
    int time; //被选中的次数
    soldier* next;
}*p[MAXL]; //哈希链数组,编号%MAXL相同的士兵放在同一个哈希链中

soldier s[MAXL]; //士兵数组
__int64 N, a, b;
int total; //自杀士兵数量
int index; //士兵数组索引

//选择士兵,num表示该士兵应该所在的哈希链的编号,x表示该士兵的编号
bool select(__int64 num, __int64 x)
{
    soldier* q;
    int flag = 0;
    for (q = p[num]; q != NULL; q = q->next) //搜索该士兵应该所在的哈希链
    {
        if (q->number == x) //找到该士兵
        {
            q->time++;
            if (q->time == 2) //被选中2次,该士兵自杀
            {
                ++total;
            }
            else if (q->time == 3) //被选中3次,结束
            {
                return true;
            }
            flag = 1;
            break;
        }
    }
    if (flag == 0) //在哈希链中未找到该士兵,即第1次选中该士兵
    {
        q = &s[index++]; //将该士兵存入士兵数组
        q->number = x;
        q->time = 1;
        q->next = p[num]; //将该士兵加入其应该所在的哈希链
        p[num] = q; //更新该哈希链的头指针
    }
    return false;
}

int main()
{
    while (cin >> N)
    {
        if (N == 0)
            break;

        cin >> a >> b;
        memset(p, NULL, sizeof(p));
        total = 0;
        index = 0;

        __int64 num = b % N; //每次选中的士兵的编号
        while (select(num % MAXL, num) == false)
        {
            num = (((a * num) % N * num) % N + b) % N;
        }
        cout << N - total << endl;
    }
    return 0;
}

继续加油。

发布了325 篇原创文章 · 获赞 1 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/Intelligence1028/article/details/105648385
今日推荐