【题解】2019年安徽大学ACM/ICPC实验室新生赛

2019年安徽大学ACM/ICPC实验室新生赛题解

A. 素数分布

对于给定的 ,求出不超过 的素数的个数。

卡掉了最最暴力的做法,但是你只需要记录一个1000以内的素数表,然后每次在这个素数表里面统计就不会超时了。

#include <bits/stdc++.h>
using namespace std;
int main() {
  vector<bool> isPrime(1001);
  isPrime[2] = true;
  for (int i = 3; i <= 1000; i++) {
    int sqt = sqrt(i);
    bool flag = true;
    for (int j = 2; flag && j <= sqt; j++)
      if (i % j == 0) flag = false;
    if (flag) isPrime[i] = true;
  }
  int T;
  cin >> T;
  while (T--) {
    int n;
    cin >> n;
    int ans = 0;
    for (int i = 2; i <= n; i++)
      if (isPrime[i]) ans++;
    cout << ans << endl;
  }
  return 0;
}

难度定位:codeforces rating 800

B.食物分配

给定四个正整数,判断这四个正整数能否被恰好划分成三组,每一组数的和相等。

设这四个数分别为 ,如果满足划分条件,则必然有 ,因此只需要对这四个数排序后判断即可。

#include <bits/stdc++.h>
using namespace std;
int main() {
  int T;
  cin >> T;
  while (T--) {
    vector<int> nps(4);
    for (auto& i : nps) cin >> i;
    sort(nps.begin(), nps.end());
    if (nps[0] + nps[1] == nps[2] && nps[2] == nps[3])
      cout << nps[2] << endl;
    else
      cout << -1 << endl;
  }
  return 0;
}

难度定位:codeforces rating 1000

C.AHUICPC(Easy Version)

询问只会有10种情况(1到10),其中只有10的情况下暴力构造的长度会超过15,对于这种情况只需要2个A和5个H就可以构造出10个子序列"AH",然后再后面补"UICPC"即可。

#include <bits/stdc++.h>
using namespace std;
int main() {
  int n;
  cin >> n;
  if (n <= 9) {
    for (int i = 0; i < n; i++) cout << 'A';
    cout << "HUICPC\n";
  } else {
    cout << "AAHHHHHUICPC\n";
  }
  return 0;
}

难度定位:codeforces rating 800

D.不定方程

根据题意, 即为 的最小公倍数 ,于是有 。可见 一定是互质的,即 。而此时只需要令 即可构造出答案。

注意因为 最大会到 ,所以两者之积有可能超过int的范围。

#include <bits/stdc++.h>
using namespace std;
int main() {
  int T;
  cin >> T;
  while (T--) {
    long long x, y;
    cin >> x >> y;
    if (__gcd(x, y) != 1)
      cout << -1 << endl;
    else
      cout << y << ' ' << x << ' ' << x * y << endl;
  }
  return 0;
}

难度定位:codeforces rating 1400

E.蕊蕊识数

因为数据量极大,所以直接用python暴力计算是会超时的。

注意到对于任意的 ,其被3除的余数都是1,因此 对3同余。

任何十进制非负整数都可以表示成 的多项式形式,其中 恰好是该十进制数的各个数位。因此任意十进制非负整数被3除的余数,都等于将它的各个十进制位的数相加后被3除的余数。换而言之,3满足所有情况的 ,而比3小的可能的答案只有2。

所以只需要判断一下2是否是答案,如果不是输出3即可。

#include <bits/stdc++.h>
using namespace std;
int main() {
  int T;
  cin >> T;
  int _max = 0;
  while (T--) {
    string str;
    cin >> str;
    int num = 0;
    for (auto &i : str) num += i - '0';
    int check = (str.back() - '0') % 2;
    bool flag = true;
    while (num >= 10) {
      if (num % 2 != check) {
        flag = false;
        break;
      }
      str = to_string(num);
      num = 0;
      for (auto &i : str) num += i - '0';
    }
    if (flag && num % 2 == check)
      cout << 2 << endl;
    else
      cout << 3 << endl;
  }
  return 0;
}

python的AC代码

T = int(input())
while T:
    T -= 1
    n = input()
    check = int(n[-1]) % 2
    n = sum([int(i) for i in n])
    flag = True
    while n > 9:
        if n % 2 != check:
            flag = False
            break
        n = str(n)
        n = sum([int(i) for i in n])
    if flag and n % 2 == check:
        print(2)
    else:
        print(3)

难度定位:codeforces rating 1700

F.蕊蕊乘车去上学

题目所求即为等车的时间期望,我们设该期望为 ,其中 表示遇到发车间隔为 的公交车的概率, 表示遇到发车间隔为 的公交车的概率。

注意到这个概率是时间上的概率,假设一辆公交车刚刚离开,那么距离下一辆公交车到达需要 分钟,而在这段时间内等车遇到的公交车的发车间隔都是 。由于两种发车间隔出现的可能性是相等的,因此遇到的公交车发车间隔是 的概率为 ,遇到的公交车发车间隔是 的概率为 。最终的答案是

#include <bits/stdc++.h>
using namespace std;
int main() {
  int a, b;
  cin >> a >> b;
  cout << fixed << setprecision(2) << (double)(a * a + b * b) / (a + b) << endl;
  return 0;
}

难度定位:codeforces rating 1600

G.AHUICPC(Hard Version)

我们令 ,且 ,如果我们构造出所有的恰好有 个“AH”的字符串,并且它们之间互不影响,然后再在其后面接上"UICPC",那么就可以得到答案。且长度为 数量级。

事实上我们每一次都用 个A和 个H来构造,由于我们保证了 ,所以我们可以把较小的 放在后面,把较大的 放在前面,这样我们可以重复利用较小的 的“H”。更形象地说,我们先取最后一项 ,此时会有 个A和 个H,接下来考虑前一项 ,我们在恰好其后有 个H的位置插入 个A。如此不断重复。

#include <bits/stdc++.h>
using namespace std;
vector<pair<int, int>> res;
int main() {
  int num;
  cin >> num;
  while (num > 0) {
    int tmp1 = sqrt(num), tmp2 = num / tmp1;
    while (tmp1 * tmp2 <= num) {
      tmp2++;
    }
    while (tmp1 * tmp2 > num) {
      tmp2--;
    }
    res.push_back(make_pair(tmp1, tmp2));
    num -= tmp1 * tmp2;
  }
  string str = "UICPC";
  res.push_back(make_pair(0, 0));
  for (int i = 0; i < res.size() - 1; i++) {
    for (int j = 0; j < res[i].second; j++) {
      str = "H" + str;
    }
    for (int j = 0; j < res[i].first - res[i + 1].first; j++) {
      str = "A" + str;
    }
  }
  cout << str << endl;
  return 0;
}

难度定位:codeforces rating 1900

H.无尽大军

抽象来说,对于起始的数字1,可以消耗2使其翻倍,即乘以2;而后既可以选择消耗2使其再乘以2,也可以消耗1使得上一次乘以 的操作变为乘以

因此对于 ,我们的操作其实是构造一个等式 ,而操作的总消耗即等于

不难发现对于最小的总消耗, 恰好为 的全体质因数,因此将 质因数分解之后把所有因子相加即可得到答案。

 #include <bits/stdc++.h>
using namespace std;
vector<pair<int, int>> res;
int main() {
  long long n;
  cin >> n;
  long long sqt = sqrt(n);
  long long ans = 0;
  for (long long i = 2; i <= sqt; i++) {
    while (n % i == 0) {
      ans += i;
      n /= i;
    }
  }
  if (n != 1) ans += n;
  cout << ans << endl;
  return 0;
}

难度定位:codeforces rating 2000

全部评论
我一个代码长度甚至还比这八道解题总和多。。。。
5 回复 分享
发布于 2019-12-04 17:25
题解很nice
3 回复 分享
发布于 2019-12-04 17:30
可惜了,当年报名了,结果却忘了去了,与队伍失之交臂真是遗憾
点赞 回复 分享
发布于 2022-10-20 20:56 安徽
学算法,就上牛客,XCPC铜牌不是梦,心动不如行动,点此下方链接报名立减20元: 基础算法入门班:https://www.nowcoder.com/courses/cover/live/724?coupon=ARgGejk 进阶数据结构专题课:https://www.nowcoder.com/courses/cover/live/707?coupon=AQDlsi4
点赞 回复 分享
发布于 2022-12-02 20:51 天津

相关推荐

10 13 评论
分享
牛客网
牛客企业服务