A. Game
给出一个数组,由0和1组成,遇到0不能走,遇到1可以没有花费的走过去。最多只能跳一次,花费x,从i跳到i + x。问从头走到尾,最少的花费是多少。
思路:只能跳一次,所以最优的方案是从第一个为0的位置开始跳,跳到最后一个为0的位置。
AC Code:
#include <bits/stdc++.h>
typedef long long ll;
const int N = 2e5 + 5;
int t, n;
int a[N];
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
std::cin >> t;
while(t --) {
std::cin >> n;
int st = 0, en = 0;
for(int i = 1; i <= n; i ++) {
std::cin >> a[i];
if(!st && !a[i])
st = i - 1;
}
for(int i = n; i >= 1; i --) {
if(!a[i]) {
en = i + 1;
break;
}
}
std::cout << en - st << '\n';
}
return 0;
}
os:一开始读错题了,一直wa,乐
B. Game of Ball Passing
n个人传球,每个人传了a[i]次,问最少需要几个球。
思路:其实只需要考虑传球次数最多的那个人。如果最多的那个人传的次数大于其他所有人的和+1,那必须用多的球,即这个人的次数减去全部人的次数是答案;其他的情况,一个球足够。至于为什么是要+1,因为如果这个最多的人在第一个传球,那还可以多加一次传球。
AC Code:
#include <bits/stdc++.h>
typedef long long ll;
const int N = 1e5 + 5;
int t, n;
ll a[N];
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
std::cin >> t;
while(t --) {
std::cin >> n;
for(int i = 1; i <= n; i ++) {
std::cin >> a[i];
}
std::sort(a + 1, a + 1 + n);
if(!a[n]) {
std::cout << 0 << '\n';
continue;
}
ll sum = 0;
bool flag = false;
for(int i = 1; i < n; i ++) {
sum += a[i];
if(sum + 1 >= a[n]) {
flag = true;
break;
}
}
std::cout << std::max((ll)1, a[n] - sum) << '\n';
}
return 0;
}
C. Weird Sum
给出一个n*m的二维数组,计算每一对相同的数字之间曼哈顿距离之和。
思路:因为是计算曼哈顿距离,所以完全可以x和y分开计算,统计所有相同的数字的位置,排序,按照前后相邻两个位置直接计算贡献。
AC Code:
#include <bits/stdc++.h>
typedef long long ll;
#define int long long
const int N = 1e5 + 5;
int t, n, m;
int a[N];
std::vector<int> row[N], col[N];
bool vis[N];
signed main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
std::cin >> n >> m;
int cnt = 0;
for(int i = 1; i <= n; i ++) {
for(int j = 1; j <= m; j ++) {
int x;
std::cin >> x;
if(!vis[x])
vis[x] = true, a[++ cnt] = x;
row[x].push_back(i);
col[x].push_back(j);
}
}
int ans = 0;
for(int i = 1; i <= cnt; i ++) {
int x = a[i];
std::sort(row[x].begin(), row[x].end());
std::sort(col[x].begin(), col[x].end());
int len = row[x].size();
for(int j = 1; j < len; j ++) {
ans += (row[x][j] - row[x][j - 1]) * (len - j) * j;
ans += (col[x][j] - col[x][j - 1]) * (len - j) * j;
}
}
std::cout << ans << '\n';
return 0;
}
D. Integral Array
给出一个数组,判断它是否满足以下条件:选择任意两个数(也可以是它本身),大数除以小数向下取整的结果都在数组中出现。
思路:因为是x / y = t,可以反过来考虑,对于x的范围,我们可以这样表示:[y * t, y * (t + 1) - 1]。所以枚举t和y,判断x的存在即可。对于区间内判断,可以采用前缀和记录。
AC Code:
#include <bits/stdc++.h>
typedef long long ll;
const int N = 1e6 + 5;
int t, n, c;
ll a[N], vis[N << 1], pre[N << 1];
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
std::cin >> t;
while(t --) {
std::cin >> n >> c;
for(int i = 1; i <= 2 * c; i ++) {
vis[i] = 0;
}
for(int i = 1; i <= n; i ++) {
std::cin >> a[i];
vis[a[i]] ++;
}
for(int i = 1; i <= 2 * c; i ++) {
pre[i] = pre[i - 1] + vis[i];
}
bool flag = true;
for(int i = 1; i <= c; i ++) {
if(!vis[i]) continue;
for(int j = 1; j * i <= c; j ++) {
if(vis[j]) continue;
if(pre[i * j - 1] != pre[i * (j + 1) - 1]) {
flag = false;
break;
}
}
if(!flag) break;
}
std::cout << (flag ? "Yes" : "No") << '\n';
}
return 0;
}