文章目录
Codeforces Round #667 (Div. 3)
A.Yet Another Two Integers Problem
题意: 给定a和b,每次可以把a+k或者a-k,
k
∈
[
1
,
10
]
k \in [1, 10]
k∈[1,10],求最少变化多少次能够使得a变成b
题解: 计算出a和b的差值,然后向上取整即可
代码:
#include <bits/stdc++.h>
using namespace std;
int const N = 2e5 + 10;
int T, n, a[N];
int main() {
cin >> T;
while(T--) {
int a, b;
cin >> a >> b;
int diff = abs(b - a);
// cout << ceil((double)diff/10)<<endl;
printf("%d\n", (int)ceil((double)diff/10));
}
return 0;
}
B.Minimum Product
题意: 给定a,b,x,y,n,每次操作可以让a–或者b–,但是a最小减到x,b最小减到y,操作次数最多为n次,问a和b经过若干次操作后,a*b的值最小是多少
题解: 假设a经过若干次后为a’,b经过若干次后为b’,则答案为res = a’*b’。要让res最小,那么a’和b’的差值要尽可能大。那么如何让差值尽可能大呢,要让小的尽可能小。但是由于x和y的限制,直接把较小的那个变化,不能达到最优值。因此,一种情况是把较小的减小,另一种是把较大的减的比原先较小的还要小。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
int const N = 2e5 + 10;
int T, n, a, b, x, y;
LL solve(int a, int b, int x, int y, int n) {
int diff_a = min(n, a - x);
a -= diff_a;
n -= diff_a;
int diff_b = min(n, b - y);
b -= diff_b;
return a * 1ll * b;
}
int main() {
cin >> T;
while(T--) {
scanf("%d%d%d%d%d", &a, &b, &x, &y, &n);
cout << min(solve(a, b, x, y, n), solve(b, a, y, x, n)) << endl;
}
return 0;
}
C.Yet Another Array Restoration
题意: 给定等差数列中的两项,给定等差数列的项数,构造一个等差数列,且使得最大值最小
题解: 由于数字较小,都不超过50,因此直接暴力即可。暴力枚举等差数列的公差,然后每次都判断最大值,求出最小的情况即可
代码:
#include <bits/stdc++.h>
using namespace std;
int const N = 1e5 + 10;
int T, n, ai[N];
vector<int> res, tmp;
int a, b;
int minv = N;
void slove(int det) {
tmp.clear();
if (b - det * (n - 1) > 0 && b - det * (n - 1) <= a) {
// if (det == 10) cout << "here" << endl;
for (int i = b - det * (n - 1); i <= b; i += det) {
// if (det == 10) cout << "push: " << i << endl;
tmp.push_back(i);
}
if (b < minv) {
minv = min(minv, b);
res = tmp;
}
}
else if (b - det * (n - 1) <= a) {
int t = b;
int cnt = 0;
while(t - det > 0) {
cnt ++;
t -= det;
}
for (int i = t, j = 0; j < n; ++j, i += det) tmp.push_back(i);
if (tmp.back() < minv) {
minv = min(minv, tmp.back());
res = tmp;
}
}
// return 1;
}
int main() {
cin >> T;
while(T--) {
res.clear();
tmp.clear();
scanf("%d%d%d", &n, &a, &b);
if (n == 2 ) {
cout << a << " " << b << endl;
continue;
}
minv = N;
int diff = b - a;
for (int i = 1; i <= diff; ++i) {
if (diff % i == 0)
slove(i);
}
for (auto r: res) cout << r << " " ;
printf("\n");
}
return 0;
}
D.Decrease the Sum of Digits
题意: 给定n和s,每次操作可以把n += 1,求至少操作多少次后能够使得n的每位数字之和小于等于s。
题解: 记n得每位之和为sum(n),如果sum(n) <= s,那么输出0;否则从最低为开始(为了保证操作次数尽可能小),如果当前sum(n)>s,那么把n得当前位数+1,直到进位(不进位的话sum(n)只增不减)。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
int const N = 2e5 + 10;
LL T, n, s;
LL check(LL x) {
LL sum = 0;
while(x) {
sum += x % 10;
x /= 10;
}
return sum;
}
int main() {
cin >> T;
while(T--) {
scanf("%lld%lld", &n, &s);
if (check(n) <= s) {
printf("0\n");
continue;
}
LL res = 0, bit = 1;
for (int i = 0; i < 18; ++i) {
LL last = n / bit % 10;
LL add = (10 - last) * bit;
res += add;
n += add;
if (check(n) <= s) break;
bit *= 10;
}
printf("%lld\n", res);
}
return 0;
}
E. Two Platforms
题意: 给定一张竖直平面上n个点,每个点坐标位(xi, yi),给定2个板子,板子的长度均为k。问将两个板子放置在哪可以保证两个板子接到的点数和最多。
∑
n
<
=
2
∗
1
0
5
,
x
i
<
=
1
0
9
,
y
i
<
=
1
0
9
,
1
<
=
k
<
=
1
0
9
\sum n <= 2*10^5, x_i<=10^9, y_i <= 10^9, 1 <= k <= 10^9
∑n<=2∗105,xi<=109,yi<=109,1<=k<=109
题解: 动态规划处理,r[i]表示用一块板子在i右侧能够接到的点最多为多少,l[i]表示用一块板子在i左侧能够接到的点最多为多少。那么答案就是
r
e
s
=
m
a
x
{
l
[
i
]
+
r
[
i
+
1
]
}
。
res = max\lbrace l[i] + r[i + 1] \rbrace 。
res=max{l[i]+r[i+1]}。本题点的坐标到达
1
0
9
10^9
109,本来应该离散化,但是可以特殊处理、利用尺取的思想就可以避免离散化,具体见代码。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
int const N = 2e5 + 10;
int T, n, x[N], k, l[N], r[N];
int main() {
cin >> T;
while(T--) {
memset(l, 0, sizeof l);
memset(r, 0, sizeof r);
scanf("%d%d", &n, &k);
for (int i = 1; i <= n; ++i) scanf("%d", &x[i]);
for (int i = 1, t; i <= n; ++i) scanf("%d", &t);
if (n == 1) {
printf("1\n");
continue;
}
sort(x + 1, x + 1 + n);
int j = n;
for (int i = n; i >= 1; --i) {
while(x[j] - x[i] > k && j >= i) j--;
r[i] = j - i + 1;
if (i < n) r[i] = max(r[i], r[i + 1]);
}
j = 1;
for (int i = 1; i <= n; ++i) {
while(x[i] - x[j] > k && j <= i) ++j;
l[i] = i - j + 1;
if (i > 1) l[i] = max(l[i], l[i - 1]);
}
int res = 1;
for (int i = 1; i < n; ++i) {
res = max(res, l[i] + r[i + 1]);
}
printf("%d\n", res);
}
return 0;
}