您的位置:首页 > 其它

Educational Codeforces Round 92 (Rated for Div. 2)

2020-07-30 18:07 369 查看

Educational Codeforces Round 92 (Rated for Div. 2)

A: LCM Problem

Problem Statement
Let LCM(x,y) be the minimum positive integer that is divisible by both x and y. For example, LCM(13,37)=481, LCM(9,6)=18.

You are given two integers l and r. Find two integers x and y such that l≤x<y≤r and l≤LCM(x,y)≤r.

Input
The first line contains one integer t (1≤t≤10000) — the number of test cases.

Each test case is represented by one line containing two integers l and r (1≤l<r≤109).

Output
For each test case, print two integers:

  • if it is impossible to find integers x and y meeting the constraints in the statement, print two integers equal to −1;
  • otherwise, print the values of x and y (if there are multiple valid answers, you may print any of them).

Example
input

4
1 1337
13 69
2 4
88 89

output

6 7
14 21
2 4
-1 -1

题意:
1、LCM(x, y) 是 x 与 y 的最小公倍数
2、在 [ l, r ] 区间内寻找 x, y 且 LCM(x,y) 也在 [ l, r ] 内
3、如果存在这样的 x, y 输出任意一组,否则输出 -1 -1

分析:
因为是输出任何一组,我们取 x = l, 那么 x 最小的倍数就是 2 x,x 与 2x 的最小公倍数就是 2x,所以判断 2x 是否在区间内就可以了。如果不在区间内,那么一定不存在这样的 x, y。因为 2 * l 是满足条件 LCM(x, y)最小的值

代码:

#include <bits/stdc++.h>
using namespace std;

int main() {
int T;
cin >> T;
while (T--) {
int l, r;
cin >> l >> r;
if (l * 2 <= r) {
cout << l << " " << l * 2 << endl;
} else {
cout << -1 << " " << -1 << endl;
}
}
return 0;
}

原题传送门

B:Array Walk

You are given an array a1,a2,…,an, consisting of n positive integers.

Initially you are standing at index 1 and have a score equal to a1. You can perform two kinds of moves:

  1. move right — go from your current index x to x+1 and add ax+1 to your score. This move can only be performed if x<n.
  2. move left — go from your current index x to x−1 and add ax−1 to your score. This move can only be performed if x>1. Also, you can’t perform two or more moves to the left in a row.

You want to perform exactly k moves. Also, there should be no more than z moves to the left among them.

What is the maximum score you can achieve?

Input
The first line contains a single integer t (1 ≤ t ≤ 10^4) — the number of testcases.

The first line of each testcase contains three integers n,k and z (2 ≤ n ≤1 0^5, 1 ≤ k ≤ n−1, 0 ≤ z ≤ min(5,k)) — the number of elements in the array, the total number of moves you should perform and the maximum number of moves to the left you can perform.

The second line of each testcase contains n integers a1,a2,…,an (1 ≤ ai ≤ 10^4) — the given array.

The sum of n over all testcases does not exceed 3⋅10^5.

Ouput
Print t integers — for each testcase output the maximum score you can achieve if you make exactly k moves in total, no more than z of them are to the left and there are no two or more moves to the left in a row.

Example
input

4
5 4 0
1 5 4 3 2
5 4 1
1 5 4 3 2
5 4 4
10 20 30 40 50
10 7 3
4 6 8 2 9 9 7 4 10 9

output

15
19
150
56

Note
In the first testcase you are not allowed to move left at all. So you make four moves to the right and obtain the score a1+a2+a3+a4+a5.

In the second example you can move one time to the left. So we can follow these moves: right, right, left, right. The score will be a1+a2+a3+a2+a3.

In the third example you can move four times to the left but it’s not optimal anyway, you can just move four times to the right and obtain the score a1+a2+a3+a4+a5.

题意:
1、在数组中有两种操作,一种是向右移动一位,一种是向左移动一位
2、限制:不能连续进行向左移动的操作——you can’t perform two or more moves to the left in a row.
3、有 k 次操作,其中最多可以进行 z 次左移操作(可以不进行左移操作
4、每次移动可以获得数组中相应位置的分数
5、在 k 次操作后使获得的分数最大

分析:
1、因为存在左移和右移两种操作,所以除了在一路向右移动的情况外我们还可以在中间某两个数字之间反复左移、右移(在 k 、z 限制下)来使获得的分数更大。

代码:

#include <bits/stdc++.h>

using namespace std;
typedef unsigned long long ULL;
const int MAX_N = 2e5 + 10;
int a[MAX_N];
ULL b[MAX_N];
ULL get (int l, int r) {
return b[r] - b[l];
}
int main() {
int T;
scanf("%d", &T);
while (T--) {
int n, k, z;
scanf("%d %d %d", &n, &k, &z);
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
b[i] += b[i - 1] + a[i];
}
ULL ans = 0;
if (z == 0) {
cout << b[k + 1] << endl;
memset(b, 0, sizeof(b));
continue;
} else {
for (int i = k + 1; i >= 0; i--) {
/// 当前位置剩余可使用操作做数
int t = k + 1 - i;
/// 左移可使用操作数
int q = z;
ULL re = b[i];
while (true) {
if (t == 0 || q == 0) {
break;
}
if (q > 0) {
re += a[i - 1];
q--;
t--;
}
if (t > 0) {
re += a[i];
t--;
}
}
if (t > 0) {
int j = i + t;
re += get(i , j);
}
ans = max(ans, re);
}
}
cout << ans << endl;
memset(b, 0, sizeof(b));
}
return 0;
}

原题传送门

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: