个人题解

A

输入是整数 特判一下25就行了

#include <iostream>
using namespace std;

int main() {
  int x;
  cin>>x;
  cout<<(x == 25 ? 0 : (x*0.2 < 5 ? 5 : 8))<<'\n';
  
  return 0;
}

B

排序 选差异度第m小的那个就行

#include <iostream>
#include <algorithm>
using namespace std;

int a[100005];

int main() {
  int t;
  cin>>t;
  while (t--) {
    int n,m,k,x;
    cin>>n>>m>>k;
    for (int i=1; i<=n; i++)
      cin>>x, a[i] = abs(x-k);
    sort(a+1, a+1+n);
    cout<<a[m]<<'\n';
  }
  
  return 0;
}

C

栈 模拟
贪心地消除

几个月前2025-03-23 牛客周赛 Round 86 出过类似做法的题目 比这题稍难:
小苯的数字消除 https://ac.nowcoder.com/acm/contest/104637/C

#include <iostream>
#include <stack>
using namespace std;

int main() {
  int n;
  string s;
  cin>>n>>s;
  stack<char> stk;
  for (auto &ch: s)
    if (!stk.empty() 
        && (stk.top() >= 'a' && stk.top() <= 'm' && ch + stk.top() == 'a' + 'z' 
            || stk.top() >= 'N' && stk.top() <= 'Z' && ch + stk.top() == 'A' + 'Z'))
      stk.pop();
    else
      stk.push(ch);
  cout<<stk.size()<<'\n';
  
  return 0;
}

D

打表?
但是数学原理是什么?

如果只分裂为, 可以获得
如果只分裂为, 可以获得
如果都可以分裂任意多次, 可以获得个, 其中
那么问题就是可以表示哪些数呢? 或者是否还需要分裂为其它完全平方数?

数论里有一个 希尔维斯特定理(Sylvester定理) 或 麦乐鸡定理(Chicken McNugget定理):

在自然数范围内,互质的两个数可以线性表示大于的所有数。

那么就一定可以表示大于的所有数
以内的, 手动计算枚举哪些能表示, 哪些不能表示, 即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14

#include <iostream>
#include <unordered_set>
using namespace std;

int main() {
  int t;
  cin>>t;
  unordered_set<int> st{2,3,5,6,8,11,14};
  long long x;
  while (t--)
    cin>>x, cout<<(st.find(x) != st.end() ? "No" : "Yes")<<'\n';
  
  return 0;
}

E

个人的一种思路 应该是最简单的方法:

先考虑把所有数都变成0, 计算最小代价, 实际上就是在每个"突变"的位置进行后缀翻转

而现在我们需要前面一段是0, 后面一段是1, 简单的想法就是把所有数变为0后, 再选择一段后缀翻转为1, 但实际上这样的代价肯定不是最优的

如果我们已经打算把某个后缀变为1, 在最开始就可以对这段后缀不进行翻转操作

减少这次操作之后, 得到的就是我们需要的"前面一段是0, 后面一段是1"的结果, 因为这段后缀的每个数都少翻转了一次

实际上我们可以断定, 最优方案的0和1的分界点一定在原来就"突变"的位置(从0到1或从1到0)

那么找到最大"突变"的位置的代价, 用总代价减去这个代价即可

#include <iostream>
using namespace std;

int main() {
  int t;
  cin>>t;
  while (t--) {
    int n;
    string s;
    cin>>n>>s;
    s = '0' + s;
    long long sum = 0;
    int mx = 0, x;
    for (int i=1; i<=n; i++) {
      cin>>x;
      if (s[i-1] != s[i]) {
        sum += x;
        mx = max(mx, x);
      }
    }
    cout<<sum-mx<<'\n';
  }
  
  return 0;
}

F

线性基板子
可以选择一个数字 而自己异或自己是0 所以可以不用考虑0的问题
求出线性基后看有没有哪个bit的基是0的 那么这个2的幂就无法表示

去年2024-10-13 牛客周赛 Round 63 也出过线性基的题目 比这题要难:
小红开灯 https://ac.nowcoder.com/acm/contest/91592/F

#include <iostream>
#include <cstring>
using namespace std;

long long a[500005], d[60];

int main() {
  int t;
  cin>>t;
  while (t--) {
    int n;
    cin>>n;
    for (int i=1; i<=n; i++)
      cin>>a[i];
    memset(d, 0, sizeof d);
    for (int i=1; i<=n; i++)
      for (int j=59; j>=0; j--)
        if (a[i]>>j&1) {
          if (d[j] == 0) {
            d[j] = a[i];
            break;
          }
          a[i] ^= d[j];
        }
    int i;
    for (i=0; i<60; i++)
      if (d[i] == 0)
        break;
    cout<<(1ll<<i)<<'\n';
  }
  
  return 0;
}