数据量比较小,直接按照题意模拟即可,可以开设 1000 个动态数组(链表),然后模拟合并操作。时间复杂度为 \Omicron(n^2) 。具体实现细节参见代码(C++):
#define n 1000
#define m 580
ll fa[n + 2], sum[n + 2], num[n + 2], ansi;
vector<ll> g[n + 2];
signed main()
{
for (ll i = 1; i <= n; ++i)
{
fa[i] = i;
g[i].emplace_back(i);
}
for (ll i = 1; i <= m; ++i)
{
ll j = (i * i + i * m) % n + 1, fj = fa[j];
for (ll k : g[fj])
{
fa[k] = fa[i];
g[fa[i]].emplace_back(k);
}
g[fj].clear();
}
ll w = 0;
for (ll i = 1; i <= n; ++i)
{
for (ll j : g[i])
{
sum[i] += j;
}
num[i] = g[i].size();
w += g[i].size();
}
for (ll i = 1; i <= n; ++i)
{
if (num[i] > num[ansi] || (num[i] == num[ansi] && sum[i] > sum[ansi]))
{
ansi = i;
}
}
printf("flag{%lld}", num[ansi] * sum[ansi]);
return 0;
}
学过算法的选手应该很快能看出,这就是一道并查集的模板题。直接用并查集知识解之即可。时间复杂度为 \Omicron(n) 。具体实现细节参见代码(C++):
#define n 1000
#define m 580
ll fa[n + 2], num[n + 2], sum[n + 2], ansi;
ll finds(ll k)
{
while (k != fa[k])
{
k = fa[k];
}
return k;
}
signed main()
{
for (ll i = 1; i <= n; ++i)
{
fa[i] = i;
}
for (ll i = 1; i <= m; ++i)
{
ll j = (i * i + i * m) % n + 1;
fa[finds(j)] = finds(i);
}
for (ll i = 1; i <= n; ++i)
{
ll k = finds(i);
num[k]++;
sum[k] += i;
}
for (ll i = 1; i <= n; ++i)
{
if (num[i] > num[ansi] || (num[i] == num[ansi] && sum[i] > sum[ansi]))
{
ansi = i;
}
}
printf("flag{%lld}", num[ansi] * sum[ansi]);
return 0;
}