第一题
奇偶排序
思路
按照既定的顺序进行排序即可
参考代码:
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
std::vector<int> solution(int n, std::vector<int>& vec) {
std::vector<int> result;
// TODO:
for (int i = 0; i < n; i++) {
if (vec[i] % 2 == 1) {
result.push_back(vec[i]);
}
}
for (int i = 0; i < n; i++) {
if (vec[i] % 2 == 0) {
result.push_back(vec[i]);
}
}
return result;
}
int main() {
int n;
std::vector<int> vec;
std::cin >> n;
std::string line_0, token_0;
getline(std::cin >> std::ws, line_0);
std::stringstream tokens_0(line_0);
while (std::getline(tokens_0, token_0, ' ')) {
vec.push_back(std::stoi(token_0));
}
std::vector<int> result = solution(n, vec);
for (auto it = result.begin(); it != result.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
return 0;
}
第二题
小艺照镜子
思路:
用马拉车算法求一下最长回文子串的长度即可,很经典
#include <cstring>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
using namespace std;
int expand(std::string s, int left, int right) {
while (left >= 0 && right < s.size() && s[left] == s[right]) {
--left;
++right;
}
return (right - left - 2) / 2;
}
string longestPalindrome(string s) {
int start = 0, end = -1;
string t = "#";
for (char c : s) {
t += c;
t += '#';
}
t += '#';
s = t;
vector<int> arm_len;
int right = -1, j = -1;
for (int i = 0; i < s.size(); ++i) {
int cur_arm_len;
if (right >= i) {
int i_sym = j * 2 - i;
int min_arm_len = min(arm_len[i_sym], right - i);
cur_arm_len = expand(s, i - min_arm_len, i + min_arm_len);
} else {
cur_arm_len = expand(s, i, i);
}
arm_len.push_back(cur_arm_len);
if (i + cur_arm_len > right) {
j = i;
right = i + cur_arm_len;
}
if (cur_arm_len * 2 + 1 > end - start) {
start = i - cur_arm_len;
end = i + cur_arm_len;
}
}
string ans;
for (int i = start; i <= end; ++i) {
if (s[i] != '#') {
ans += s[i];
}
}
return ans;
}
int solution(std::string s) {
int result;
// TODO:
result = longestPalindrome(s).size();
return result;
}
int main() {
std::string s;
std::cin >> s;
int result = solution(s);
std::cout << result << std::endl;
return 0;
}
第三题
交换后的or
描述和思路
给定两组长度为n的二进制串,请问有多少种方法在第一个串中交换两个不同位置上的数字,使得这两个二进制串“或”的 结果发生改变?
思路:统计一下会产生数值变化的情况即可
#include <iostream>
#include <string>
int solution(int n, std::string str1, std::string str2) {
int ans;
// TODO:
int cc = 0;
for (int i = 0; i < n; i++) {
if (str1[i] == '0' && str2[i] == '0') {
cc++;
}
}
int cc1 = 0;
for (int i = 0; i < n; i++) {
if (str1[i] == '1') {
cc1++;
}
}
ans += cc1 * cc;
cc = 0;
for (int i = 0; i < n; i++) {
if (str1[i] == '1' && str2[i] == '0') {
cc++;
}
}
cc1 = 0;
for (int i = 0; i < n; i++) {
if (str1[i] == '0' && str2[i] == '1') {
cc1++;
}
}
ans += cc1 * cc;
return ans;
}
int main() {
int n;
std::string str1;
std::string str2;
std::cin >> n;
std::cin >> str1;
std::cin >> str2;
int result = solution(n, str1, str2);
std::cout << result << std::endl;
return 0;
}
第四题
去除整数
描述和思路
已知存在集合A包含n个整数,从1到n。 存在m个整数a[1…m]。 在集合A中去除这m个整数的的倍数。 输出集合中包含的元素的个数。
思路:经典二进制枚举+gcd+lcm
#include <iostream>
#include <map>
#include <sstream>
#include <string>
#include <vector>
using namespace std;
typedef long long ll;
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
ll lcm(ll a, ll b) { return a / gcd(a, b) * b; }
int solution(int n, int m, std::vector<int>& a) {
// TODO:
int SUM = 0;
for (int i = 0; i < m; i++) {
if (a[i] == 0) {
i--, m--;
}
}
for (int i = 0; i < (1 << m); i++) //二进制枚举
{
ll sum = 1;
int cnt = 0, res = -1;
for (int j = 0; j < m; j++) {
if (1 & (i >> j)) {
sum = lcm(sum, a[j]);
cnt++;
}
}
if (cnt % 2 == 1)
res = 1;
if (cnt)
SUM = SUM + (n / sum) * res;
}
return n - SUM;
}
int main() {
int n;
int m;
std::vector<int> vec;
std::cin >> n;
std::cin >> m;
std::string line_0, token_0;
getline(std::cin >> std::ws, line_0);
std::stringstream tokens_0(line_0);
while (std::getline(tokens_0, token_0, ' ')) {
vec.push_back(std::stoi(token_0));
}
int result = solution(n, m, vec);
std::cout << result << std::endl;
return 0;
}