zoukankan      html  css  js  c++  java
  • 2021暑假模拟赛4

    A[CF1552A(800)]

    本质上是求序列的不动点个数,也就是和最终排好序的序列相同的地方。

    #include <bits/stdc++.h>
    using namespace std;
    int main() {
      int T;
      cin >> T;
      while (T --> 0) {
        int N;
        cin >> N;
        string S;
        cin >> S;
        string T(S);
        sort(T.begin(), T.end());
        int Ans = 0;
        for (int i = 0; i < N; ++i) {
          if (S[i] != T[i]) {
            Ans ++;
          }
        }
        cout << Ans << '
    ';
      }
    }
    View Code

    B[CF1110C(1500)]

    观察一下容易得出如果$A$存在某一位为$0$,那么答案为将所有为$0$的位填满。如果不存在为$0$的位,那么需要从$A$中找一个子集使得子集是$A$的约数,枚举一下约数即可。

    #include <bits/stdc++.h>
    using namespace std;
    int pre[] = {
    1,
    1,
    5,
    1,
    21,
    1,
    85,
    73,
    341,
    89,
    1365,
    1,
    5461,
    4681,
    21845,
    1,
    87381,
    1,
    349525,
    299593,
    1398101,
    178481,
    5592405,
    1082401};
    int main() {
      int Q;
      cin >> Q;
      vector<int> A(Q);
      for (int i = 0; i < Q; ++i) {
        cin >> A[i];
      }
      for (int i = 0; i < Q; ++i) {
        int h = -1;
        for (int j = 0; j < 30; ++j) {
          if (A[i] >> j & 1) {
            h = j;
          }
        }
        int S = 0;
        for (int j = 0; j < h; ++j) {
          if (!(A[i] >> j & 1)) {
            S |= 1 << j;
          }
        }
        int Ans = 0;
        if (S == 0) {
          cout << pre[h - 1] << '
    ';
        } else {
          Ans = (A[i] | S);
          cout << (A[i] | S) << '
    ';
        }
      } 
    }
    View Code

    C[1025B(1600)]

    这个题的做法较多。由于求任意一个解即可,那么最方便的是找一个质因子。先求出所有$lcm(A_i,B_i)$的$gcd$,那么这里面肯定包含一个合法的质因子,于是枚举里面的质因子判断是否合法即可。

    #include <bits/stdc++.h>
    using namespace std;
    vector<int> GetPrime(int n) {
      vector<bool> mark(n + 1);
      vector<int> Prime;
      for (int i = 2; i <= n; ++i) {
        if (!mark[i]) {
          Prime.emplace_back(i);
        }
        for (int j = 0; j < Prime.size() && i * Prime[j] <= n; ++j) {
          mark[i * Prime[j]] = true;
          if (i % Prime[j] == 0) {
            break;
          }
        }
      }
      return Prime;
    }
    int main() {
      ios::sync_with_stdio(false);
      cin.tie(nullptr);
      vector<int> P = GetPrime(100000);
      int N;
      cin >> N;
      vector<long long> A(N);
      vector<long long> B(N);
      for (int i = 0; i < N; ++i) {
        cin >> A[i] >> B[i]; 
      }
      long long g = 0;
      for (int i = 0; i < N; ++i) {
        long long C = A[i] / __gcd(A[i], B[i]) * B[i];
        g = __gcd(g, C);
      }
      for (int i : P) {
        if (g % i == 0) {
          cout << i << '
    ';
          exit(0);
        }
      }
      vector<long long> ALL;
      for (auto i : A) {
        ALL.push_back(i);
      }
      for (auto i : B) {
        ALL.push_back(i);
      }
      for (auto i : ALL) {
        if (__gcd(i, g) >= 2) {
          cout << __gcd(i, g) << '
    ';
          exit(0);
        }
      }
      cout << -1 << '
    ';
    }
    View Code

    D[CF1517D(1800)]

    先观察出几个有用的性质:

    1.去的路和返回的路肯定是一样的,否则不优

    2.$k$必须为偶数,否则无法返回

    由这两个性质可以把题目转化为求从任意一个点出发走$frac{k}{2}$步的最远距离。考虑$dp[i][j][k]$表示走了$k$步,走到了$(i,j)$,转移枚举相邻的点走下一步即可。

    #include <bits/stdc++.h>
    using namespace std;
    const long long Inf = numeric_limits<long long> :: max() / 3;
    int main() {
      ios::sync_with_stdio(false);
      cin.tie(nullptr);
      int N, M, K;
      cin >> N >> M >> K;
      vector<vector<int>> A(N, vector<int> (M));
      for (int i = 0; i < N; ++i) {
        for (int j = 0; j < M - 1; ++j) {
          cin >> A[i][j];        
        }
      }
      vector<vector<int>> B(N, vector<int> (M));
      for (int i = 0; i < N - 1; ++i) {
        for (int j = 0; j < M; ++j) {
          cin >> B[i][j];
        }
      }
      if (K % 2 == 1) {
        for (int i = 0; i < N; ++i) {
          for (int j = 0; j < M; ++j) {
            cout << -1 << " 
    "[j == M - 1];
          }
        }
        exit(0);
      }
      vector<vector<pair<int, int>>> adj(N * M);
      auto id = [&] (int X, int Y) -> int {
        return X * M + Y;
      };
      for (int i = 0; i < N; ++i) {
        for (int j = 0; j < M - 1; ++j) {
          adj[id(i, j)].emplace_back(id(i, j + 1), A[i][j]);
          adj[id(i, j + 1)].emplace_back(id(i, j), A[i][j]);
        }
      }
      for (int i = 0; i < N - 1; ++i) {
        for (int j = 0; j < M; ++j) {
          adj[id(i, j)].emplace_back(id(i + 1, j), B[i][j]);
          adj[id(i + 1, j)].emplace_back(id(i, j), B[i][j]);
        }
      }
      vector<vector<vector<long long>>> dp(N, vector<vector<long long>> (M, vector<long long> (K + 1, Inf)));
      for (int i = 0; i < N; ++i) {
        for (int j = 0; j < M; ++j) {
          dp[i][j][0] = 0;
        }
      }
      for (int k = 0; k < K / 2; ++k) {
        for (int i = 0; i < N; ++i) {
          for (int j = 0; j < M; ++j) {
            int X = id(i, j);
            for (auto [Y, W] : adj[X]) {
              int ii = Y / M;
              int jj = Y % M;
              dp[ii][jj][k + 1] = min(dp[ii][jj][k +1], dp[i][j][k] + W);
            }
          }
        }
      }
      for (int i = 0; i < N; ++i) {
        for (int j = 0; j < M; ++j) {
          cout << (dp[i][j][K / 2] == Inf ? -1 : dp[i][j][K / 2] * 2) << " 
    "[j == M - 1];
        }
      }
    }
    View Code

     相信通过这几场比赛,大家肯定已经熟练掌握位运算以及分解质因数的操作了!

  • 相关阅读:
    Spyder 快捷键大全
    上传代码到github,出现 git@github.com: Permission denied (publickey) 错误
    Linux ubuntu 安装 openssh-server 报错
    win10删除「此电脑」中的文档、视频、音乐、下载、图片、桌面等6个文件夹的方法
    IDEA 光标闪烁问题
    委托、Action泛型委托、Func泛型委托、Predicate泛型委托的用法
    C#6.0的新语法特性
    创建多个网站
    发送短信功能(C#)
    VS开发Windows服务
  • 原文地址:https://www.cnblogs.com/19992147orz/p/15091646.html
Copyright © 2011-2022 走看看