总结:这是在cf上打的第二场比赛,做的太慢了,后面几题也没有思路,需要继续刷题
A. Favorite Sequence
先输出一个头部的元素,然后输出一个尾部的元素
如果有奇数个,必然中间会剩余一个,直接输出就好了
#include <bits/stdc++.h>
#define lowbit(x) ((x) & (-x))
using namespace std;
typedef long long ll;
const int N = 2010;
int a[N];
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
int t, n;
cin >> t;
while (t--) {
cin >> n;
for (int i = 1; i <= n; i++) cin >> a[i];
int l = 1, r = n;
while (l < r) {
cout << a[l] << " " << a[r] << " ";
l++, r--;
}
if (n % 2) cout << a[l];
cout << endl;
}
return 0;
}
B - Last Year’s Substring
问截去中间的字符串,两端的能不能组成“2020”, 分类讨论即可
#include <bits/stdc++.h>
#define lowbit(x) ((x) & (-x))
using namespace std;
typedef long long ll;
const int N = 2010;
int a[N];
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
int t;
cin >> t;
while (t--) {
int n, flag = 0, flag2 = 0;
cin >> n;
getchar();
string s;
getline(cin, s);
int q = s.length();
if (s.substr(0, 4) == "2020" || s.substr(q - 4) == "2020") flag = 1;
else if (s[0] == '2' && s.substr(q - 3) == "020") flag = 1;
else if (s[0] == '2' && s[1] == '0' && s.substr(q - 2) == "20") flag = 1;
else if (s.substr(0, 3) == "202" && s[q - 1] == '0') flag = 1;
if (flag) cout << "YES" << endl;
else cout << "NO" << endl;
}
return 0;
}
C - Unique Number
如果最后的数尽可能小的话,那位数一定要少,所以把包含的大数放在后面
用一个循环从9往下匹配即可,能减的话就减掉
#include <bits/stdc++.h>
#define lowbit(x) ((x) & (-x))
using namespace std;
typedef long long ll;
const int N = 2010;
const int inf = 0x3f3f3f3f;
vector<int> v;
int ans, x, book[20];
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
int t;
cin >> t;
while (t--) {
int x; cin >> x;
if (x > 45) cout << -1 << endl;
else {
string res = "";
int now = 9;
while(x && now) {
if (x >= now) {
res = to_string(now) + res;
x -= now;
}
now--;
}
cout << res << endl;
}
}
return 0;
}
D - Add to Neighbour and Remove
枚举能分成的段数,求出分成当前段时,每段的和是多少,然后开始遍历整个数组,把几个数字的和加起来:
- 如果小于分段和,那么继续加
- 如果等于分段和,那么这一段就ok了,继续下一段
- 如果大于分段和,那肯定分成当前段是不可能的了
另外就是把n个数合并成x个,需要的操作数是n - x
#include <bits/stdc++.h>
#define lowbit(x) ((x) & (-x))
using namespace std;
typedef long long ll;
const int N = 3010;
const int inf = 0x3f3f3f3f;
ll sum[N], a[N];
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
int t, n;
cin >> t;
while (t--) {
cin >> n;
ll all = 0;
for (int i = 1; i <= n; i++) {
cin >> a[i];
all += a[i];
}
for (int k = n; k >= 1; k--) {
ll now = 0;
if (all % k == 0) {
int ok = 1, x = all / k;
for (int j = 1; j <= n; j++) {
now += a[j];
if (now > x) {
ok = 0;
break;
} else if (now == x) {
now = 0;
}
}
if (ok) {
cout << n - k << endl;
break;
}
}
}
}
return 0;
}
E1 - Close Tuples (easy version)
问的是选三个数,最大值与最小值差值不超过2,有多少种选法?
先排序,先选一个最小值,然后确定最大值,再这个范围中选两个即可
#include <bits/stdc++.h>
#define lowbit(x) ((x) & (-x))
using namespace std;
typedef long long ll;
const int N = 1000010;
const int inf = 0x3f3f3f3f;
int a[N];
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
ios::sync_with_stdio(false);
cin.tie(0);
int t, n;
cin >> t;
while (t--) {
cin >> n;
for (int i = 1; i <= n; i++) cin >> a[i];
sort(a + 1, a + 1 + n);
ll sum = 0, j = 1;
for (int i = 1; i <= n; i++) {
while (j + 1 <= n && a[j + 1] - a[i] <= 2) j++;
ll cnt = j - i;
if (cnt >= 2) {
sum += cnt * (cnt - 1) / 2;
}
}
cout << sum << endl;
}
return 0;
}
E2 - Close Tuples (hard version)
本题与上一题区别就是最大值与最小值的差值是变量,另外选取的元素个数也是变量。
因此预先求出组合数,其他的与上一题相同
#include <bits/stdc++.h>
#define lowbit(x) ((x) & (-x))
using namespace std;
typedef long long ll;
const int N = 2e5 + 10;
#define modl 1000000007
ll a[N], c[N][105];
void init() {
c[0][0] = 1;
for (int i = 1; i < N; i++) {
c[i][0] = 1;
if (i < 105) c[i][i] = 1;
for (int j = 1; j < min(i, 105); j++) {
c[i][j] = (c[i - 1][j - 1] + c[i - 1][j]) % modl;
}
}
}
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
int t;
scanf("%d", &t);
init();
while (t--) {
int n, m, k;
scanf("%d%d%d", &n, &m, &k);
for (int i = 1; i <= n; i++) scanf("%lld", &a[i]);
sort(a + 1, a + 1 + n);
ll sum = 0, j = 1;
for (int i = 1; i <= n; i++) {
while (j + 1 <= n && a[j + 1] - a[i] <= k) j++;
int cnt = j - i;
if (cnt >= m - 1) {
sum = (sum + c[cnt][m - 1]) % modl;
}
}
printf("%lld\n", sum);
}
return 0;
}
F - The Treasure of The Segments
问是否存在一个区间,他与其他区间都有相交的部分?如果不存在,那么至少需要删掉多少个才能实现这个条件?
做法:遍历每个区间,求他左边与他不相交的个数,再求他右边与他不相交的个数,记录一下这个值,求出最小值即可
#include <bits/stdc++.h>
#define lowbit(x) ((x) & (-x))
using namespace std;
typedef long long ll;
const int N = 2e5 + 10;
int l[N], r[N];
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
int t;
scanf("%d", &t);
while (t--) {
int n;
scanf("%d", &n);
vector<int> left, right;
for (int i = 1; i <= n; i++) {
scanf("%d%d", &l[i], &r[i]);
left.push_back(l[i]);
right.push_back(r[i]);
}
sort(left.begin(), left.end());
sort(right.begin(), right.end());
int ans = n;
for (int i = 1; i <= n; i++) {
int num1 = lower_bound(right.begin(), right.end(), l[i]) - right.begin();
int num2 = n - (upper_bound(left.begin(), left.end(), r[i]) - left.begin());
ans = min(ans, num1 + num2);
}
printf("%d\n", ans);
}
return 0;
}