由于士兵总数最多为 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;
}
继续加油。