A. Fashion in Berland
题意:有\(n\)个数,需要满足正好有\(n-1\)个\(0\)或者\(n=1\)时正好一个\(1\)。
记录\(1\)的个数,判断即可。
点击查看代码
void solve() {int n;std::cin >> n;std::vector<int> a(n);for (int i = 0; i < n; ++ i) {std::cin >> a[i];}int cnt = std::count(a.begin(), a.end(), 1);if ((n == 1 && cnt == 1) || (n > 1 && cnt == n - 1)) {std::cout << "YES\n";} else {std::cout << "NO\n";}
}
B. s-palindrome
题意:判断一个字符串是不是镜像的,所谓镜像就是对应字母是对称的。
需要一点点耐心找对称的字母。
点击查看代码
void solve() {std::string s;std::cin >> s;std::map<char, char> mp;std::vector<std::string> ss{"AA", "bd", "HH", "II", "MM", "OO", "oo", "YY", "XX", "xx", "pq", "TT", "UU", "vv", "VV", "WW", "ww"};for (auto & t : ss) {mp[t[0]] = t[1];mp[t[1]] = t[0];}int n = s.size();for (int l = 0, r = n - 1; l <= r; ++ l, -- r) {if (mp[s[l]] != s[r]) {std::cout << "NIE\n";return;}}std::cout << "TAK\n";
}
C. Exponential notation
题意:给你一个大数,把它转换为科学计数法表示。
模拟题,需要一点细节。
点击查看代码
void solve() {std::string s;std::cin >> s;int n = s.size();int l = -1, r = -1;for (int i = 0; i < n; ++ i) {if (s[i] != '0' && s[i] != '.') {l = i;break;}}for (int i = n - 1; i >= 0; -- i) {if (s[i] != '0' && s[i] != '.') {r = i;break;}}int p = s.find('.');if (p == s.npos) {p = n;}if (l == -1) {std::cout << 0 << "\n";return;} std::string ans;ans += s[l];if (l < r) {ans += '.';}for (int i = l + 1; i <= r; ++ i) {if (s[i] != '.') {ans += s[i];}} if (l + 1 != p) {ans += "E";if (l < p) {ans += std::to_string(p - l - 1);} else {ans += std::to_string(p - l);}}std::cout << ans << "\n";
}
D. Swaps in Permutation
题意:给你一个数组,以及\(m\)个可以交换的位置,求数组操作后的最大字典序。
根据冒泡排序,对于每个可以交换的联通块,我们都可以让它降序排序。那么用并查集维护联通块,每个联通块单独排序。
点击查看代码
struct DSU {std::vector<int> fa, cnt;DSU(int _n) {init(_n);}void init(int _n) {fa.assign(_n, 0);cnt.assign(_n, 1);std::iota(fa.begin(), fa.end(), 0);}int find(int x) {return x == fa[x] ? x : fa[x] = find(fa[x]);}bool merge(int x, int y) {x = find(x), y = find(y);if (x == y) {return false;}fa[y] = x;cnt[x] += cnt[y];return true;}bool same(int x, int y) {return find(x) == find(y);}int size(int x) {return cnt[find(x)];}
};void solve() {int n, m;std::cin >> n >> m;std::vector<int> a(n);for (int i = 0; i < n; ++ i) {std::cin >> a[i];}DSU dsu(n);for (int i = 0; i < m; ++ i) {int u, v;std::cin >> u >> v;-- u, -- v;dsu.merge(u, v);}std::vector<std::vector<int>> g(n);for (int i = 0; i < n; ++ i) {g[dsu.find(i)].push_back(i);}for (int i = 0; i < n; ++ i) {std::vector<int> b;for (auto & x : g[i]) {b.push_back(a[x]);}std::sort(b.begin(), b.end(), std::greater<int>());for (int j = 0; j < b.size(); ++ j) {a[g[i][j]] = b[j];}}for (int i = 0; i < n; ++ i) {std::cout << a[i] << " \n"[i == n - 1];}
}
E. Xor-sequences
题意:给你\(n\)个数,如果两个数异或后二进制下1的个数是3的倍数,这两个就可以在序列中相邻。求有多少种长度为\(k\)的序列。
如果我们建立一个邻接矩阵,那么\(g[i][j]\)表示\(j\)能否在\(i\)后面,那么问题转换为求一个图中节点个数为\(k\)的路径有多少,变成了矩阵乘法板子。
点击查看代码
const int N = 100;
using M = std::array<std::array<Z, N>, N>;int n;
i64 k;struct Mat {M mat;Mat() {init();}void init() {for (int i = 0; i < n; ++ i) {for (int j = 0; j < n; ++ j) {mat[i][j] = 0;}}}std::array<Z, N> & operator [](const int i) {return mat[i];}
};Mat operator * (Mat & a, Mat & b) {static Mat c;for (int i = 0; i < n; ++ i) {for (int j = 0; j < n; ++ j) {c[i][j] = 0;for (int k = 0; k < n; ++ k) {c[i][j] += a[i][k] * b[k][j];}}}return c;
}void solve() {std::cin >> n >> k;std::vector<i64> a(n);for (int i = 0; i < n; ++ i) {std::cin >> a[i];}auto count = [&](i64 x) -> int {int res = 0;while (x) {if (x & 1) {++ res;}x >>= 1;}return res;};Mat g;for (int i = 0; i < n; ++ i) {for (int j = 0; j < n; ++ j) {if (count(a[i] ^ a[j]) % 3 == 0) {g[i][j] = 1;}}}Mat res;for (int i = 0; i < n; ++ i) {res[i][i] = 1;}-- k;while (k) {if (k & 1) {res = res * g;}g = g * g;k >>= 1;}Z ans = 0;for (int i = 0; i < n; ++ i) {for (int j = 0; j < n; ++ j) {ans += res[i][j];}}std::cout << ans << "\n";
}
F. Couple Cover
题意:对于每个\(p\),求\(a\)中有多少\(i, j\)满足\(a[i] \times a[j] >= p\)。
发现值域只有\(3e6\),考虑预处理,可以记录每个数出现的个数,然后枚举每个数的倍数,那么我们记f[k] = \(a[i] \times a[j] == k\)的个数,那么\(a[i] \times a[j] < k\)的个数就是\(\sum_{i=1}^{k-1} f[k]\)。 总个数有\(\frac{n(n-1)}{2}\)个,那么对于每个\(p\),答案就是\(\frac{n(n-1)}{2} - \sum_{i=1}^{p-1} f[p]\)。
点击查看代码
void solve() {int n;std::cin >> n;const int N = 3e6 + 5;std::vector<int> cnt(N);for (int i = 0; i < n; ++ i) {int x;std::cin >> x;++ cnt[x];}std::vector<i64> f(N);for (int i = 1; i < N; ++ i) {for (int j = i; j < N; j += i) {f[j] += (i64)cnt[i] * (cnt[j / i] - (i == j / i));}}for (int i = 1; i < N; ++ i) {f[i] += f[i - 1];}int m;std::cin >> m;while (m -- ) {int x;std::cin >> x;std::cout << (i64)n * (n - 1) - f[x - 1] << "\n";}
}