rating:800--1300--1700--1900
A. Array Balancing
给出两个数组a和b,两个数组的数字个数都是一样的,怎样通过操作构造两个数组使得所要求的数最小。
思路:因为是求相邻数的差的绝对值,所以我们只需要把较大的数放入b组,较小的数放入a组即可。
AC Code:
#include <bits/stdc++.h>
#pragma GCC optimize(2)
template <typename T>
inline void read(T &x) {
x = 0;
int f = 1;
char ch = getchar();
while (!isdigit(ch)) {
if (ch == '-')
f = -1;
ch = getchar();
}
while (isdigit(ch)) {
x = x * 10 + ch - '0', ch = getchar();
}
x *= f;
}
template <typename T>
void write(T x) {
if (x < 0)
putchar('-'), x = -x;
if (x > 9)
write(x / 10);
putchar(x % 10 + '0');
}
#define INF 0x3f3f3f3f
typedef long long ll;
const double PI = acos(-1);
const double eps = 1e-6;
const int mod = 1e9 + 7;
const int N = 55;
int t;
int n, a[N], b[N];
int main() {
// freopen("test.in","r",stdin);
// freopen("output.in", "w", stdout);
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cin >> t;
while (t--) {
std::cin >> n;
for (int i = 1; i <= n; i++) {
std::cin >> a[i];
}
for (int i = 1; i <= n; i++) {
std::cin >> b[i];
}
for (int i = 1; i <= n; i++) {
if (a[i] > b[i])
std::swap(a[i], b[i]);
}
ll ans = 0;
for (int i = 1; i < n; i++) {
ans += abs(a[i] - a[i + 1]);
ans += abs(b[i] - b[i + 1]);
}
std::cout << ans << '\n';
}
return 0;
}
B. Getting Zero
给出一个数组,对于每个数,给出两种操作,怎样操作使得达到目的所需的操作次数最少,对每个数求最小的操作次数。
思路: 看到给出的这个数,通过计算可知,这个数是,模该数等于0,可以使结果等于这个数或者是这个数的倍数。
(1)BFS搜索:通过怎样的操作使得满足结果。
AC Code:
#include<bits/stdc++.h>
using namespace std;
const int maxn=3e5+10;
const int mod=32768;
int dist[maxn];
int bfs(int n)
{
memset(dist,-1,sizeof dist);
dist[n]=0;
queue<int>q;
q.push(n);
while(!q.empty())
{
int now=q.front();
q.pop();
if(now==0) return dist[now];
int nex=now*2%mod;
if(dist[nex]==-1)
{
dist[nex]=dist[now]+1;
q.push(nex);
}
nex=(now+1)%mod;
if(dist[nex]==-1)
{
dist[nex]=dist[now]+1;
q.push(nex);
}
}
}
int main()
{
int tt;
cin>>tt;
while(tt--)
{
int n;
cin>>n;
cout<<bfs(n)<<" ";
}
cout<<'\n';
return 0;
}
os:如果T了换个编译方式或许就可以了。。。
(2)位运算:考虑先给x加1,一直到的奇数倍然后进行15-k次乘2操作,枚举所有情况取最小值即可。
AC Code:
#include <bits/stdc++.h>
#pragma GCC optimize(2)
template <typename T>
inline void read(T &x) {
x = 0;
int f = 1;
char ch = getchar();
while (!isdigit(ch)) {
if (ch == '-')
f = -1;
ch = getchar();
}
while (isdigit(ch)) {
x = x * 10 + ch - '0', ch = getchar();
}
x *= f;
}
template <typename T>
void write(T x) {
if (x < 0)
putchar('-'), x = -x;
if (x > 9)
write(x / 10);
putchar(x % 10 + '0');
}
#define INF 0x3f3f3f3f
typedef long long ll;
const double PI = acos(-1);
const double eps = 1e-6;
const int mod = 1e9 + 7;
const int N = 32768;
int n, x;
int solve(int a) {
if (a == 0)
return 0;
int ans = 1e9;
ans = std::min(ans, N - a);
for (int i = 1; i <= 15; i++) {
int t = ((1 << i) - 1)&x;
int k;
if (t == 0)
k = 0;
else
k = (1 << i) - t;
ans = std::min(ans, k + 15 - i);
}
return ans;
}
int main() {
// freopen("test.in","r",stdin);
// freopen("output.in", "w", stdout);
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cin >> n;
for (int i = 1; i <= n; i++) {
std::cin >> x;
std::cout << solve(x) << ' ';
}
std::cout << '\n';
return 0;
}
C. Water the Trees
给很多树浇水,奇数日期浇水长1,偶数日期浇水长2,当然也可以选择某一天不浇水,问所有树都长到同一高度最少需要几天。
思路:暴力枚举。对于每一棵树需要长到的高度,我们可以计算需要长奇数高度的树个数,因为奇数高度至少需要一天是奇数日期,而需要长偶数高度的树则不必考虑若需要奇数天过多也会增加所需要的总天数,这时候我们就需要减少奇数日期的需要,则就把最大值+1,则改变奇偶性,两种情况取最小值即可。
AC Code:
#include <bits/stdc++.h>
#pragma GCC optimize(2)
template <typename T>
inline void read(T &x) {
x = 0;
int f = 1;
char ch = getchar();
while (!isdigit(ch)) {
if (ch == '-')
f = -1;
ch = getchar();
}
while (isdigit(ch)) {
x = x * 10 + ch - '0', ch = getchar();
}
x *= f;
}
template <typename T>
void write(T x) {
if (x < 0)
putchar('-'), x = -x;
if (x > 9)
write(x / 10);
putchar(x % 10 + '0');
}
#define INF 0x3f3f3f3f
typedef long long ll;
const double PI = acos(-1);
const double eps = 1e-6;
const int mod = 1e9 + 7;
const int N = 3e5 + 5;
ll n, a[N], t;
ll solve(ll max) {
ll res = 0, cnt = 0, ans;
for (int i = 1; i <= n; i++) {
res += (max - a[i]);
if ((max - a[i]) % 2)
cnt++;
}
if (res % 3 == 0) {
ans = std::max(cnt * (ll)2 - 1, res / 3 * 2);
} else if (res % 3 == 1) {
ans = std::max(cnt * (ll)2 - 1, res / 3 * 2 + 1);
} else {
ans = std::max(cnt * (ll)2 - 1, res / 3 * 2 + 2);
}
return ans;
}
int main() {
// freopen("test.in","r",stdin);
// freopen("output.in", "w", stdout);
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cin >> t;
while (t--) {
std::cin >> n;
ll maxn = -1;
for (int i = 1; i <= n; i++) {
std::cin >> a[i];
maxn = std::max(maxn, a[i]);
}
std::cout << std::min(solve(maxn), solve(maxn + 1)) << '\n';
}
return 0;
}
os:还有一个二分的写法,,,二分太辣鸡了没写
若有错误请指教,谢谢!
orzorz