AtCoder Beginner Contest 178

导读:
简单的题目,只说明题意,或者直接说明结论
下面的难题,会做详细的解释和证明
立个flag,在座的大佬们做个见证:一个月刷60场ABC,现在2021/7/10,第二十五天,已打卡二十一场。

F - Contrast

题解参考地址

我们reverse数组过后发现,a数组与b数组最多只会重复一种数字c,那么,在其他合法方案的下标所在的位置,如果有ai和bi都不等于c的话,那么我们就可以将c与bi的位置交换一下,这样就会消灭掉一处重复的位置。遍历下来,如果c全部消灭则合法,否则不合法

#include <bits/stdc++.h>
using namespace std;
const int N = 200005;
int n;
int a[N], b[N];
int main()
{
  cin >> n;
  for (int i = 1; i <= n; i ++ )
    scanf("%d", &a[i]);
  for (int i = 1; i <= n; i ++ )
    scanf("%d", &b[i]);
  reverse(b + 1, b + 1 + n);
  int l = n + 1, r = 0, c = -1;
  for (int i = 1; i <= n; i ++ )
    if (c == -1 && a[i] == b[i])
    {
      c = a[i];
      l = i, r = i;
    }
    else if (c != -1 && a[i] == b[i])
    {
      r = i;
    }
  for (int i = 1; i <= n; i ++ )
    if (c != -1 && c != a[i] && c!= b[i] && l <= r)
    {
      swap(b[i], b[l]);
      l ++;
    }
  if (l <= r) cout << "No" << endl;
  else
  {
    cout << "Yes" << endl;
    for (int i = 1; i <= n; i ++ )
      printf("%d ", b[i]);
    puts("");
  }
  return 0;
}

E - Dist Max

参考题解地址

给定n个点(xi, yi),n大小为2e5,求最长的两点的曼哈顿距离.
降维,将o(n^2)降到o(n)加上快排,为O(nlogn)
曼哈顿距离:|x1-x2| + |y1 - y2|
如果直接暴力枚举的话,时间复杂度为O(n^2)
我们去绝对值
若:x1 > x2, y1 > y2那么dist = x1 - x2 + y1 - y2
化简得:dist = (x1 + y1) - (x2 + y2)
若:x1 > x2, y2 > y1 那么dist = x1 - x2 + y2 - y1
化简得:dist = (x1 - y1) - (x2 - y2)
若:x2 > x1, y1 > y2那么dist = x2 - x1 + y1 - y2
化简得:dist = (x2 - y2) - (x1 - y1)
若:x2 > x1, y2 > y1 那么dist = x2 - x1 + y2 - y1
化简得:dist = (x2 + y2) - (x1 + y1)
所以,我们可得化简后得结果
dist = max(|(x1 + y1) - (x2 + y2)|, |(x1 - y1) - (x2 - y2)|)
所以,如果我们要找到两个曼哈顿距离最远得两个点得话,就是处理出x1 + y1x1 - y1这两个数组,然后分别拿最大的减去最小得,然后再取一个max

#include <bits/stdc++.h>
using namespace std;
const int N = 200005;
int n;
int add[N], sub[N];
int main()
{
  cin >> n;
  for (int i = 0, x, y; i < n; i ++ )
  {
    scanf("%d%d", &x, &y);
    add[i] = x + y;
    sub[i] = x - y;
  }
  sort(add, add + n);
  sort(sub, sub + n);
  cout << max(add[n - 1] - add[0], sub[n - 1] - sub[0]) << endl;
  return 0;
}

D - Redistribution

线性DP求方案数:
我们用dp[i]来表示数字为i的时候,合法的方案数是多少。
则dp[i] = dp[0] + dp[1] + … + dp[i - 3]

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2005, mod = 1e9 + 7;
int n;
ll dp[N], s[N];
int main(){
  cin >> n;
  s[0] = 1;
  for (int i = 1; i <= n; i ++ )
  {
    if (i - 3 >= 0) dp[i] = s[i - 3] % mod;
    s[i] = (s[i - 1] + dp[i]) % mod;
  }
  cout << dp[n] << endl;
  return 0;
}

C - Ubiquity

求方案数,问有无穷个0~9之间的数字,随意取出n个排列组合在一起,问同时含有至少一个0和9的方案数为多少?
容斥原理:对于n个数,有9^n个没有0的序列,有9^n个没有9的序列,有8^n个没有0也没有1的序列,总方案数为10^n个。那么,要么只包含只包含0,要么只包含9,要么都不包含0和9的方案数为:9^n+9^n-8^n
那么,综合到一块求实,至少同时包含0和9的方案数为:10^n-9^n-9^n+8^n

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int mod = 1e9 + 7;
int n;
int qmi(int a, int b)
{
  int ans = 1;
  while (b)
  {
    if (b & 1) ans = ans * a % mod;
    b >>= 1;
    a = a * a % mod;
  }
  return ans;
}
signed main(void)
{
  cin >> n;
  cout << (qmi(10, n) - qmi(9, n) - qmi(9, n) + qmi(8, n) + mod + mod) % mod << endl;
  return 0;
}

B - Product Max

#include <bits/stdc++.h>
using namespace std;
#define int long long
signed main()
{
  int a, b, c, d; cin >> a >> b >> c >> d;
  cout << max(max(a*c, a * d), max(b * c, b * d)) << endl;
  return 0;
}

A - Not

#include <bits/stdc++.h>
using namespace std;
#define int long long
signed main()
{
  int a; cin >> a;
  if (a) cout << 0 << endl;
  else cout << 1 << endl;
  return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值