补完题 发一下个人题解

A

模拟

#include <iostream>
using namespace std;

int main() {
  string s, t = "while";
  cin>>s;
  int cnt = 0;
  for (int i=0; i<5; i++)
    if (s[i] != t[i])
      cnt++;
  cout<<cnt<<'\n';
  
  return 0;
}

B

前缀和

#include <iostream>
using namespace std;

long long a[100005], s[100005];

int main() {
  int n;
  cin>>n;
  for (int i=1; i<=n; i++)
    cin>>a[i], s[i] = s[i-1] + a[i];
  long long mx = 0;
  for (int i=1; i<=n; i++)
    mx = max(mx, s[i]-s[max(i-10, 0)]);
  cout<<mx<<'\n';
  
  return 0;
}

C

前缀最大值

#include <iostream>
using namespace std;

int a[200005], mx[200005];

int main() {
  int t;
  cin>>t;
  while (t--) {
    int n;
    cin>>n;
    for (int i=1; i<=n; i++)
      cin>>a[i], mx[i] = max(mx[i-1], a[i]);
    int ans = 0;
    for (int i=n; i>=1; i--)
      if (mx[i-1] > a[i])
        ans = max(ans, mx[i-1]+a[i]);
    cout<<ans<<'\n';
  }
  
  return 0;
}

D

求连续自然数的段数吧 注意长度为1每个都看作单独的段

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

int main() {
  int t;
  cin>>t;
  while (t--) {
    int n,x;
    cin>>n;
    vector<int> vec;
    for (int i=1; i<=n; i++)
      cin>>x, vec.push_back(x);
    sort(vec.begin(), vec.end());
    int cnt = 0, l = 0, r = -1, t = 0;
    for (auto &x: vec) {
      if (x > r+1) {
        cnt += l == r ? t : 1;
        l = x;
        t = 0;
      }
      r = x;
      t++;
    }
    cnt += l == r ? t : 1;
    cout<<cnt-2<<'\n';
  }
  
  return 0;
}

E

题意是仅选择两行 或两列 或一行一列
其中两行可以重复 这时候就相当于什么也不做
我们只要关注所有行的1的个数的种类 和所有列的1的个数的种类
然后讨论这四种情况最后形成的图案

  • 什么也不做: 个数为0的行数为n
  • 选择两行: 个数为0的行数为n-2, 个数为m的行数为2
  • 选择两列: 个数为0的列数为m-2, 个数为n的行数为2
  • 选择一行一列: 个数为1的行数为n-1, 个数为m-1的行数为1, 个数为1的列数为m-1, 个数为n-1的列数为1
#include <iostream>
#include <cstring>
#include <unordered_map>
using namespace std;

int ax[1005], ay[1005];

int main() {
  int t;
  cin>>t;
  while (t--) {
    int n,m;
    cin>>n>>m;
    char ch;
    memset(ax, 0, sizeof(int)*(n+1));
    memset(ay, 0, sizeof(int)*(m+1));
    for (int i=1; i<=n; i++)
      for (int j=1; j<=m; j++)
        cin>>ch, ax[i] += ch == '1', ay[j] += ch == '1';
    unordered_map<int, int> mpx, mpy;
    for (int i=1; i<=n; i++)
      mpx[ax[i]]++;
    for (int i=1; i<=m; i++)
      mpy[ay[i]]++;
    if (mpx[0] == n
        || mpx[0] == n-2 && mpx[m] == 2
        || mpy[0] == m-2 && mpy[n] == 2
        || mpx[1] == n-1 && mpx[m-1] == 1 && mpy[1] == m-1 && mpy[n-1] == 1)
      cout<<"YES"<<'\n';
    else
      cout<<"NO"<<'\n';
  }
  
  return 0;
}

F

根据唯一分解定理

其因子个数为

依据是乘法原理 从每种质因子pi中选出0~ki个该因子

由于只有2既是偶数又是质数 而只有奇数*奇数=奇数
假设p1是质因数2 则其奇因子个数实际上就是

那么思路就是预处理出1~1e6的每个数的阶乘的因子个数和奇因子个数
求法是利用递推 对当前的数n质因数分解 对于它的每个因数pi 在n-1的结果上除掉之前的贡献 再乘上新的贡献

时间稍微有点紧

#include <iostream>
#include <vector>
#include <unordered_map>
using namespace std;
const int M = 998244353;

long long a[1000005], b[1000005];

long long pow(long long a, int k) {
  return k?pow(a*a%M,k/2)*(k%2?a:1)%M:1;
}

void get_factor(int n, vector<pair<int, int>> &vec) {
  for (int i=2; i*i<=n; i++) {
    if (n%i == 0) {
      int cnt = 0;
      while (n%i == 0)
        n /= i, cnt++;
      vec.push_back({i, cnt});
    }
  }
  if (n != 1)
    vec.push_back({n, 1});
}

int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  unordered_map<int, int> mp;
  a[1] = 1; b[1] = 1;
  for (int n=2; n<=1000000; n++) {
    vector<pair<int, int>> vec;
    get_factor(n, vec);
    a[n] = a[n-1]; b[n] = b[n-1];
    for (auto &[p, k]: vec) {
      if (mp.find(p) == mp.end())
        mp[p] = 1;
      int t = pow(mp[p], M-2)*(mp[p]+k)%M;
      if (p != 2)
        a[n] *= t, a[n] %= M;
      b[n] *= t, b[n] %= M;
      mp[p] += k;
    }
  }
  int t,n;
  cin>>t;
  while (t--)
    cin>>n, cout<<a[n]*pow(b[n], M-2)%M<<' ';
  
  return 0;
}