Coding Practice,48天强训(32)
Topic 1:素数回文
素数回文_牛客题霸_牛客网
更贴近应用层,考察一些基础知识点,当复习很不错
#include <bits/stdc++.h>
using namespace std;// 判断是否为素数
bool is_prime(long long n)
{if (n <= 1) return false;if (n == 2 || n == 3) return true;if (n % 2 == 0 || n % 3 == 0) return false;for (long long i = 5; i * i <= n; i += 6) {if (n % i == 0 || n % (i + 2) == 0) return false;}return true;
}// 构造题目定义的“回文数”
long long cp(int t)
{string s = to_string(t);// to_string(t)用于将数字转换为字符串string rev = s;reverse(rev.begin(), rev.end());// 反转函数rev.erase(0, 1); // 去掉开头一位,避免重复中间数 17 = 171 而不是1771string result = s + rev;return stoll(result); // 转成 long long
}int main()
{int t; cin >> t;long long pd = cp(t);if (is_prime(pd)) cout << "prime" << endl;else cout << "noprime" << endl;return 0;
}
把轮子的底层贴出来,方便复习
#include <iostream>
using namespace std;
// 判断是否为素数
bool is_prime(long long n)
{if (n <= 1) return false;if (n == 2 || n == 3) return true;if (n % 2 == 0 || n % 3 == 0) return false;for (long long i = 5; i * i <= n; i += 6) {if (n % i == 0 || n % (i + 2) == 0) return false;}return true;
}// 手写:整数转字符串(类似 to_string)
string my_to_string(int t)
{// 特殊情况:如果数字是 0,直接返回字符串 "0"if (t == 0) return "0";string res; // 用来保存转换后的字符串bool negative = false; // 判断是否为负数// 如果数字是负数,记录下来并转换成正数处理if (t < 0) {negative = true; // 标记为负数t = -t; // 将负数转为正数(方便后续处理)}// 将数字按位分解,转换成字符并追加到结果字符串while (t > 0) {// 取当前数字的最后一位,并将其转换为字符('0' 的 ASCII 码是 48)char digit = (t % 10) + '0';res += digit; // 将字符追加到结果字符串t /= 10; // 去掉最后一位数字,继续处理剩余部分}// 如果原始数字是负数,在字符串末尾添加负号if (negative) res += '-';// 由于数字是反向存储的(个位在最前),需要反转字符串int i = 0, j = res.length() - 1; // 使用两个指针从两端向中间扫描while (i < j) {swap(res[i], res[j]); // 交换两个位置的字符i++; // 左指针向右移动j--; // 右指针向左移动}return res; // 返回反转后的字符串
}// 手写:字符串反转(类似 reverse)
void my_reverse(string& s)
{int i = 0, j = s.length() - 1; // 使用两个指针,左指针 i 从 0 开始,右指针 j 从字符串末尾开始while (i < j) {swap(s[i], s[j]); // 交换 i 和 j 指向的字符i++; // 左指针向右移动j--; // 右指针向左移动}
}// 手写:删除字符串第一个字符(类似 erase(0, 1))
void my_erase_first_char(string& s)
{// 从索引 1 开始,将每个字符左移一位for (int i = 1; i < s.length(); ++i) {s[i - 1] = s[i]; // 左移字符}s.pop_back(); // 删除最后一个字符(由于左移了,所以原始的第一个字符已经移除)
}// 手写:字符串转 long long(类似 stoll)
long long my_stoll(const string& s)
{long long res = 0; // 初始化结果为 0// 遍历字符串中的每个字符,逐个转换为数字并累加到结果中for (char c : s) {res = res * 10 + (c - '0'); // 将字符转换为数字并加到结果中}return res; // 返回转换后的 long long 值
}// 手写构造题目定义的“回文数”
long long cp(int t)
{string s = my_to_string(t); // 把数字 t 转为字符串string rev = s; // 复制原字符串,用来反转my_reverse(rev); // 反转 rev 字符串my_erase_first_char(rev); // 删除 rev 的第一个字符(避免重复)string result = s + rev; // 将原字符串和反转后的部分拼接起来,形成回文数return my_stoll(result); // 将拼接后的字符串转换回 long long 类型并返回
}int main()
{int t; cin >> t;long long pd = cp(t);if (is_prime(pd)) cout << "prime" << endl;else cout << "noprime" << endl;return 0;
}
Topic 2:活动安排
活动安排_牛客题霸_牛客网
#include <bits/stdc++.h>using namespace std;bool compare(pair<int, int> a, pair<int, int> b)
{return a.second < b.second; // 按结束时间升序排
}int main()
{int n; cin >> n;vector<pair<int, int>> act(n);for (auto& a : act) cin >> a.first >> a.second;sort(act.begin(), act.end(), compare); // 按结束时间排int res = 1;// 可行活动数int lt = act[0].second;// 上个活动的结束时间for (int i = 1; i < n; i++){if (act[i].first >= lt){res++;lt = act[i].second;}}cout << res << endl;return 0;
}
比较简单,先开始还准备用小根堆做,后来发现不用,模拟一下就行了
Topic 3:合唱团
合唱团_牛客题霸_牛客网
网易的困难题,多做几遍
#include <bits/stdc++.h>
using namespace std;typedef long long ll;const int INF = LLONG_MAX; // 定义最大值
const int MINF = LLONG_MIN; // 定义最小值// 求解函数
void solve(int n, int K, int d, vector<int>& a)
{// dpMAX[i][k] 表示以 a[i] 为结尾,选择 k 个元素时的最大乘积// dpMIN[i][k] 表示以 a[i] 为结尾,选择 k 个元素时的最小乘积vector<vector<ll>> dpMAX(n, vector<ll>(K + 1, 0)); // 初始化 dpMAX 数组vector<vector<ll>> dpMIN(n, vector<ll>(K + 1, 0)); // 初始化 dpMIN 数组// 初始化:k = 1 时,以每个元素结尾的最大/最小乘积for (int i = 0; i < n; ++i) {dpMAX[i][1] = a[i]; // 每个元素作为独立的选择dpMIN[i][1] = a[i]; // 每个元素作为独立的选择}ll ans = MINF; // 初始化答案为最小值for (int i = 0; i < n; ++i) // 遍历所有元素{for (int k = 2; k <= min(i + 1, K); ++k) // 遍历选择的元素个数 k,从 2 到 K{for (int j = max(0, i - d); j < i; ++j) // 遍历 j 的范围,确保坐标差值 <= d{// 更新 dpMAX[i][k] 为在前一个状态(dpMAX[j][k-1] 和 dpMIN[j][k-1])的基础上,选择 a[i] 进行乘积计算dpMAX[i][k] = max(dpMAX[i][k], max(dpMAX[j][k - 1] * a[i], dpMIN[j][k - 1] * a[i]));// 选择更大的乘积, 选择前一个最大/最小乘积与当前元素的乘积// 更新 dpMIN[i][k] 为在前一个状态(dpMAX[j][k-1] 和 dpMIN[j][k-1])的基础上,选择 a[i] 进行乘积计算dpMIN[i][k] = min(dpMIN[i][k], min(dpMAX[j][k - 1] * a[i], dpMIN[j][k - 1] * a[i]));// 选择更小的乘积, 选择前一个最大/最小乘积与当前元素的乘积}} ans = max(ans, dpMAX[i][K]);// 更新最终结果,取所有可能的最大乘积}cout << ans << endl;// 输出最终的最大乘积结果return;
}int main()
{int n, k, d; cin >> n; // 输入数组长度 nvector<int> a(n); // 创建长度为 n 的数组 afor (auto& e : a) cin >> e; // 输入数组 a 的每个元素cin >> k >> d; // 输入选择元素个数 k 和索引差值最大值 dsolve(n, k, d, a); // 调用 solve 函数求解问题return 0;
}