注意: \color{red}{注意:} 注意: 个人博客传送门
A. Turtle Puzzle: Rearrange and Negate
思路:
- 因为可以任意排序,所以只需要输出每一个数绝对值的总和
时间复杂度: O ( n ) O(n) O(n)
void solve() {
int n;
std::cin >> n;
std::vector<int> a(n);
for (int i = 0; i < n; i++) {
std::cin >> a[i];
a[i] = abs(a[i]);
}
std::cout << std::accumulate(a.begin(), a.end(), 0) << "\n";
}
B. Turtle Math: Fast Three Task
思路:
- 每次可以进行删除一个数或者选一个数加
1
- 如果最终的余数(
mod
)为0
,就一定不需要操作 - 如果余数为
2
,或者序列中存在某个数的余数等于mod
,就只需要操作1
次 - 否则一定需要
2
次
时间复杂度: O ( n ) O(n) O(n)
void solve() {
int n;
std::cin >> n;
std::vector<int> a(n);
for (int i = 0; i < n; i++) {
std::cin >> a[i];
a[i] %= 3;
}
int sum = std::accumulate(a.begin(), a.end(), 0);
int mod = sum % 3;
if (mod == 0) {
std::cout << "0\n";
return ;
}
if (std::count(a.begin(), a.end(), mod) || mod == 2) {
std::cout << "1\n";
} else {
std::cout << "2\n";
}
}
C. Turtle Fingers: Count the Values of k
思路:
- 首先我们观察这个式子 l = k × a x × b y l=k\times a^{x} \times b^{y} l=k×ax×by
- 可以看出, a x a^x ax 和 b y b^y by 一定是 l l l 的因子,那么,我们可以得到 { l % a x = 0 l % b y = 0 \begin{cases} l \space \% \space a^x = 0 \\ l \space \% \space b^y = 0 \end{cases} {l % ax=0l % by=0
- 然后我们直接枚举 a a a 和 b b b 的指数即可,然后推导出 k = l a x b y k = \frac{\frac{l}{a^x}}{b^y} k=byaxl
时间复杂度: O ( l o g a l × l o g b ( l / i ) ) O(log_al \times log_b(l / i)) O(logal×logb(l/i))
void solve() {
int a, b, l;
std::cin >> a >> b >> l;
std::set<int> st;
for (int i = 1; l % i == 0; i *= a) {
for (int j = 1; l / i % j == 0; j *= b) {
st.insert(l / i / j);
}
}
std::cout << st.size() << "\n";
}
D. Turtle Tenacity: Continual Mods
思路:
- 一个序列所有数从左到右互相取模,可以发现,只要最小的数在最前面,那么一定最终答案不为
0
- 所以,我们可以判断,最小的数的个数,如果为
1
,那么一定可以 - 如果在除去最小的数的剩下的序列中,找到一个数
mod min != 0
,那么一定可以,因为它的余数一定比min
更小,那就可以把这个数放到那个最小的数前面,构成一个以更小的数开头的新序列
时间复杂度: O ( n ) O(n) O(n)
void solve() {
int n;
std::cin >> n;
std::vector<int> a(n);
for (int i = 0; i < n; i++) {
std::cin >> a[i];
}
std::sort(a.begin(), a.end());
int min = a[0];
if (std::count(a.begin(), a.end(), min) == 1) {
std::cout << "YES\n";
return ;
}
for (int i = 1; i < n; i++) {
if (a[i] % min != 0) {
std::cout << "YES\n";
return ;
}
}
std::cout << "NO\n";
}
E. Turtle vs. Rabbit Race: Optimal Trainings
题目大意为:
- 给你一个序列,你可以获得分数,只要你可以在
[l, r]
这个区间内获得尽可能多的能量,但不能大于u
,当然,你也可以获得超出给定值(u
)的能量,但这样会使你的能量减少。求一个你可以获得最多能量的区间右端点r
。
思路:
- 可以先求个前缀和,这样就保证了单调性,然后二分右端点
- 只要发现
r == n
时,u - sum[l, r] < s[l, r + 1] - u
,那么输出r
- 否则
s[l, r + 1] - u < u - sum[l, r]
,这样可以获得更大的分数,输出r + 1
时间复杂度: O ( q × l o g n ) O(q\times logn) O(q×logn)
void solve() {
int n;
std::cin >> n;
std::vector<int> a(n);
for (int i = 0; i < n; i++) {
std::cin >> a[i];
}
std::vector<i64> s(n + 1);
for (int i = 0; i < n; i++) {
s[i + 1] = s[i] + a[i];
}
int q;
std::cin >> q;
while (q--) {
int l, u;
std::cin >> l >> u;
int left = l, right = n;
while (left < right) {
int mid = left + right + 1 >> 1;
if (u + s[l - 1] >= s[mid]) {
left = mid;
} else {
right = mid - 1;
}
}
if (left == n || u - (s[right] - s[l - 1]) < s[right + 1] - s[l - 1] - u) {
std::cout << right << " ";
} else {
std::cout << right + 1 << " ";
}
}
std::cout << "\n";
}