2021暑假模拟赛8

A[CF1208A(900)]

由于异或的性质,容易找到序列出现$%3$的规律。

#include <bits/stdc++.h>
using namespace std;
int main() {
  int T;
  cin >> T;
  while (T --) {
    int A, B, N;
    cin >> A >> B >> N;
    if (N % 3 == 0) {
      cout << A << '\n';
    } 
    if (N % 3 == 1) {
      cout << B << '\n';
    }
    if (N % 3 == 2) {
      cout << (A ^ B) << '\n';
    }
  }
  return 0;
}
View Code

B[CF1541C(1400)]

可以发现把边从小到大串起来比较优,于是把$d$从小到大排序,利用前缀和计算答案即可。

#include <bits/stdc++.h>
using namespace std;
int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  int T;
  cin >> T;
  while (T --> 0) {
    int N;
    cin >> N;
    vector<long long> d(N);
    for (int i = 0; i < N; ++i) {
      cin >> d[i];
    }
    sort(d.begin(), d.end());
    long long Ans = d[N - 1];
    long long S = 0;
    for (int i = 0; i < N; ++i) {
      Ans -= 1LL * i * d[i];
      Ans += S;
      S += d[i];
    }
    cout << Ans << '\n';
  }
}
View Code

C[CF1529C(1600)]

需要一个观察,当每个点的取值为$l[i]$或$r[i]$时答案比较优,因为取极值的答案总会更好一些。考虑$dp[x][0/1]$表示$x$点的取值,简单分类讨论转移即可。

#include <bits/stdc++.h>
using namespace std;
int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  int T;
  cin >> T;
  while (T --> 0) {
    int N;
    cin >> N;
    vector<vector<int>> V(N, vector<int> (2));
    for (int i = 0; i < N; ++i) {
      for (int j = 0; j < 2; ++j) {
        cin >> V[i][j];
      }
    }
    vector<vector<int>> adj(N);
    for (int i = 0; i < N - 1; ++i) {
      int X, Y;
      cin >> X >> Y;
      X --;
      Y --;
      adj[X].push_back(Y);
      adj[Y].push_back(X);
    }
    vector<vector<long long>> dp(N, vector<long long> (2));
    auto dfs = [&] (auto &&f, int X, int F) -> void {
      for (int Y : adj[X]) {
        if (Y != F) {
          f(f, Y, X);
          for (int i = 0; i < 2; ++i) {
            dp[X][i] += max(dp[Y][0] + abs(V[X][i] - V[Y][0]), dp[Y][1] + abs(V[X][i] - V[Y][1]));
          }
        }
      }
    };
    dfs(dfs, 0, -1);
    cout << max(dp[0][0], dp[0][1]) << '\n';
  }
}
View Code

D[CF1188B(2300)]

考虑这个式子的形式,发现很像平方差公式,于是两边同时乘以$(a_i-a_j)$,变成$(a^4_i-a^4_j) = k(a_i-a_j)$ $mod$ $p$。

移项可得$a^4_j-ka_j=a^4_i-ka_i$,于是利用$map$计数即可。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
using namespace std;
int n, p, k;
map<int, int> mp;
int main() {
    scanf("%d%d%d", &n, &p, &k);
    for(int i = 1; i <= n; ++i) {
        int t; scanf("%d", &t);
        ++mp[((1LL * t * t % p * t % p * t % p - 1LL * k * t % p) % p + p) % p];
    }
    int ans = 0;
    for(map<int, int> :: iterator it = mp.begin(); it != mp.end(); ++it) ans = (ans + 1LL * it -> second * (it -> second - 1) / 2 % p) % p;
    printf("%d\n", ans);
    return 0;
}
View Code

 

posted @ 2021-08-09 21:08  19992147  阅读(56)  评论(0编辑  收藏  举报