QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#603612 | #9309. Graph | RozannaHuang | WA | 1ms | 3732kb | C++14 | 2.4kb | 2024-10-01 17:48:14 | 2024-10-01 17:48:14 |
Judging History
answer
#include <iostream>
#include <vector>
#include <unordered_set>
#include <algorithm>
using namespace std;
const int MOD = 998244353;
// 并查集实现
vector<int> parent, size;
// 查找根节点
int find(int x) {
if (parent[x] != x) {
parent[x] = find(parent[x]); // 路径压缩
}
return parent[x];
}
// 合并操作
void unite(int x, int y) {
int rootX = find(x);
int rootY = find(y);
if (rootX != rootY) {
if (size[rootX] < size[rootY]) swap(rootX, rootY);
parent[rootY] = rootX;
size[rootX] += size[rootY];
}
}
// 计算所有连通块的数量
vector<int> countConnectedComponents(int n) {
unordered_set<int> roots;
for (int i = 1; i <= n; ++i) {
roots.insert(find(i));
}
// 返回所有连通块的大小
vector<int> componentSizes;
for (int root : roots) {
componentSizes.push_back(size[root]);
}
return componentSizes;
}
// 计算生成树的数量
long long countTrees(const vector<int>& sizes) {
int k = sizes.size(); // 连通块数量
if (k == 0) return 0; // 没有连通块
if (k == 1) return 1; // 只有一个连通块
// 计算生成树的数量
long long totalWays = 1;
// 计算每对连通块之间的边的数量
for (int i = 0; i < k; ++i) {
for (int j = i + 1; j < k; ++j) {
// 每对连通块之间有两种连接方式
totalWays = (totalWays * 2) % MOD;
}
}
// 乘上每个连通块内部的生成树数量
for (int size : sizes) {
// 每个连通块有 (size) 选择的边
totalWays = (totalWays * size) % MOD;
}
return totalWays;
}
int main() {
int n;
cin >> n;
// 初始化并查集
parent.resize(n + 1);
size.assign(n + 1, 1); // 每个集合的初始大小为1
for (int i = 1; i <= n; ++i) {
parent[i] = i; // 初始化每个元素的父节点
}
// 按素数的倍数合并
for (int i = 2; i <= n; ++i) {
for (int j = 2 * i; j <= n; j += i) {
unite(i, j);
}
}
// 统计连通块的数量和大小
vector<int> componentSizes = countConnectedComponents(n);
// 计算最小生成树的数量
long long result = countTrees(componentSizes);
cout << result << '\n';
return 0;
}
詳細信息
Test #1:
score: 0
Wrong Answer
time: 1ms
memory: 3732kb
input:
4
output:
16
result:
wrong answer expected '8', found '16'