Codeforces Round #667 (Div. 3).md
目录
A. Yet Another Two Integers Problem
大意:
给出两个数a和b,对于a每次可以加上或者减去1到10里的任意一个数
问多少次操作后可以得到b
思路:
直接算abs(a-b)/10向上取整即可
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 5;
typedef long long LL;
int t;
int main() {
cin >> t;
while (t--) {
int a, b, res = 0;
cin >> a >> b;
res = abs(a - b) / 10 + ((abs(a-b)%10)!=0);
cout << res << endl;
}
return 0;
}
B. Minimum Product
大意:
给出a,b,x,y,n
现在要求a和b一共减去不大于n的数,且a和b不能小于x和y
问\(a*b\)最小是多少
思路:
要么是先将a减到底,要么是将b减到底
因为a+b的和确定,那么两者的差越大,乘积就越小
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 5;
typedef long long LL;
int t;
int main() {
cin >> t;
while (t--) {
LL a, b, x, y, n, res;
cin >> a >> b >> x >> y >> n;
LL newa = a, newb = b;
newa=max(a-n,x);
if(a-n<x){
newb = max(b - n+(a - newa), y);
}
res = newa * newb;
newa = a, newb = b;
newb=max(b-n,y);
if(b-n<y){
newa = max(a - n+(b - newb), x);
}
cout << min(res,newa*newb) << endl;
}
return 0;
}
C. Yet Another Array Restoration
大意:
给出n,x,y
求一个n项等差数列,满足:包含x和y且每一项都为正整数,并且等差数列的最大值最小
思路:
先求y和x的差,然后看这个差最多能被分成多少份,不够的再在x前面以及y的后面添加即可
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 5;
typedef long long LL;
int t;
int main() {
cin >> t;
while (t--) {
int n, x, y;
cin >> n >> x >> y;
int sub = y - x;
int l = sub;
for (int i = 1; i <= sub; i++) {
if (sub % i == 0) {
if (1 + sub / i <= n) {
l = i;
break;
}
}
}
int rest = n - (1 + sub / l);
int lrest = ((x-1) / l);
int rrest = 0;
if (lrest < rest) {
rrest += rest - lrest;
}
else{
lrest = rest;
}
for (int i = lrest; i >=1; i--) {
cout << x - i * l << ' ';
}
for (int i = 1; i <= (1 + sub / l);i++) {
cout << x + (i - 1) * l << ' ';
}
for (int i = 1; i <= rrest;i++){
cout << y + i * l << ' ';
}
cout << endl;
}
return 0;
}
D. Decrease the Sum of Digits
大意:
给出两个数n和s,问把n加多少个1才能使n的数位和小于等于s
思路:
从前到后求n的数位前缀和,如果前缀和不小于s,那么后面都要填0
注意特判,wa哭了...
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 5;
typedef long long LL;
int t;
int main() {
cin >> t;
while (t--) {
LL suma = 0, sumb = 0;
LL n = 0;
string a, b;
cin >> a >> b;
a = "0" + a;
b = "0" + b;
for (int i = 1; i < b.size(); i++) {
sumb = sumb * 10 + b[i] - '0';
}
for (int i = 1; i < a.size(); i++) {
n = 10 * n + a[i] - '0';
suma += a[i] - '0';
}
if (suma <= sumb) {
cout << "0" << endl;
continue;
}
suma = 0;
int pos = 0;
for (int i = 1; i < a.size(); i++) {
suma += a[i] - '0';
if (suma < sumb) continue;
pos = i - 1;
break;
}
a[pos]++;
LL res = 0;
for (int i = 0; i <= pos; i++) {
res = res * 10 + a[i] - '0';
}
for (int i = pos + 1; i < a.size(); i++) {
res = res * 10;
}
cout << res - n << endl;
}
return 0;
}
E. Two Platforms
大意:
给出n个雨滴的坐标,他们都在往下落,现在给两个长度为k的平板,问最多能接到多少雨滴
思路:
y坐标没有用,所以只需要考虑两个长度为k的区间,最多能包含多少点
贪心的想,这两个区间肯定是不重合最好,所以可以用了l[i]维护这个点左边的长度为k的板子能接的最多的雨滴
r[i]代表这个点右边能接多少,然后枚举i算l[i]+r[i+1]即可
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5;
typedef long long LL;
int t, a[N];
int l[N], r[N];
int main() {
cin >> t;
while (t--) {
int n, k;
cin >> n >> k;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
for (int i = 0; i < n; i++) {
int x;
cin >> x;
}
l[0] = 0;
r[n + 1] = 0;
sort(a + 1, a + n + 1);
for (int i = 1; i <= n; i++) {
int pos = lower_bound(a + 1, a + n + 1, a[i] - k) - a;
int tmp = i - pos + 1;
l[i] = max(l[i - 1], tmp);
}
for (int i = n; i >= 0; i--) {
int pos = upper_bound(a + 1, a + n + 1, a[i] + k) - a - 1;
int tmp = pos - i + 1;
r[i] = max(r[i + 1], tmp);
}
int res = 0;
for (int i = 1; i <= n; i++) {
res = max(res, l[i] + r[i + 1]);
}
cout << res << endl;
}
return 0;
}
F. Subsequences of Length Two
大意:
给出两个字符串s和t,其中t的长度为2
现在可以将s中的字符最多修改k次,问修改后s中有多少子序列与t相同
思路:
\(dp[i][j][l]\)代表前i个字符中修改j个字符,且出现\(t[0]l\)次时的答案
然后根据\(a[i]\)的情况进行更新即可,具体看代码
需要注意的是,如果t0=t1,只需要用公式求出
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 5;
typedef long long LL;
int n, k;
LL dp[205][205][205];
string a, b;
int main() {
cin >> n >> k;
cin >> a >> b;
a = " " + a;
b = " " + b;
if (b[1] == b[2]) {
int s = 0;
for (int i = 1; i <= n; i++) {
if (a[i] == b[1]) s++;
}
s = min(n, s + k);
cout << s * (s - 1) / 2 << endl;
return 0;
}
memset(dp, 0x8c, sizeof dp);
LL res = 0;
for (int i = 0; i <= k; i++) dp[0][i][0] = 0;
for (int i = 1; i <= n; i++) {
for (int j = 0; j <= k; j++) {
for (int l = 0; l <= i; l++) {
dp[i][j][l] = dp[i - 1][j][l];
if (a[i] == b[1]) {
dp[i][j][l] = max(dp[i][j][l], dp[i - 1][j][l - 1]);
} else if (j) {
dp[i][j][l] = max(dp[i][j][l], dp[i - 1][j - 1][l - 1]);
}
if (a[i] == b[2]) {
dp[i][j][l] = max(dp[i][j][l], dp[i - 1][j][l] + l);
} else if (j) {
dp[i][j][l] = max(dp[i][j][l], dp[i - 1][j - 1][l] + l);
}
res = max(res, dp[i][j][l]);
}
}
}
cout << res << endl;
return 0;
}