1573. 云烟的军团重组

解法一

数据量比较小,直接按照题意模拟即可,可以开设 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; }