2021暑假模拟赛3
A[HDU6950(1200)]
可以发现本质上相当于把$\frac{N-1}{2}$所有空着的为$0$的位变成了$1$,求出最高位即可算出。
#include <bits/stdc++.h> using namespace std; int main() { int T; cin >> T; while (T --> 0) { long long N; cin >> N; int B = 0; while ((1LL << B) <= (N - 1) / 2) { B ++; } cout << (1LL << B) - 1 << '\n'; } }
B[CF1404A(1500)]
可以发现每个位置对$K$同余的位置都需要相同,也就是如果$i$ $mod$ $K=j$ $mod$ $K$,那么$S[i$ $mod$ $K]==S[j$ $mod$ $K]$。于是首先判断是否同一个同余系下的位置都相同,然后考虑$0$和$1$个数相等的条件,只需要看是否对于前$k$个位置存在一种改变$?$的方式使得$0$和$1$的个数相等。
#include <bits/stdc++.h> using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int T; cin >> T; while (T --) { int n, k; cin >> n >> k; string s; cin >> s; bool ok = true; for (int i = 0; i < n; ++i) { if (s[i] != '?') { for (int j = i - k; j >= 0; j -= k) { if (s[j] == '?') { s[j] = s[i]; } else if (s[j] == s[i]) { break; } else { ok = false; break; } } for (int j = i + k; j < n; j += k) { if (s[j] == '?') { s[j] = s[i]; } else if (s[j] == s[i]) { break; } else { ok = false; break; } } } } vector<vector<int> > pre(n + 1, vector<int> (2)); for (int i = 0; i < n; ++i) { for (int j = 0; j < 2; ++j) { pre[i + 1][j] = pre[i][j]; } if (s[i] != '?') { pre[i + 1][s[i] - '0'] ++; } } for (int i = 1; i <= n; ++i) { if (i >= k) { if (pre[i][0] - pre[i - k][0] > k / 2 || pre[i][1] - pre[i - k][1] > k / 2) { ok = false; } } } if (ok) { cout << "YES" << '\n'; } else { cout << "NO" << '\n'; } } return 0; }
C[CF1458A(1600)]
看见这个形式会联想到辗转相减法$gcd(A,B)=gcd(B,A-B)$,将剩余的项都减去第一项,变成$gcd(A_1+B_j,A_2-A_1,...,A_N-A_1)$。发现只有第一项是变的,于是先将后面定值预处理出来再每次单独$gcd$即可。
#include <bits/stdc++.h> using namespace std; int main() { int N, M; cin >> N >> M; vector<long long> A(N); for (int i = 0; i < N; ++i) { cin >> A[i]; } vector<long long> B(M); for (int i = 0; i < M; ++i) { cin >> B[i]; } long long g = 0; for (int i = 0; i < N - 1; ++i) { g = __gcd(g, A[i] - A[i + 1]); } for (int i = 0; i < M; ++i) { cout << abs(__gcd(g, A[0] + B[i])) << " \n"[i == M - 1]; } }
D[CF1466E(1800)]
看到这个式子发现跟$j$关系较大,于是将$j$提到前面,然后其他两项可以分开来算。于是先枚举$j$,然后按位枚举,先预处理这一位在所有$X$中出现的次数,根据$and$和$or$的性质进行简单的讨论即可。
#include <bits/stdc++.h> using namespace std; const int P = 1000000000 + 7; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int T; cin >> T; while (T --) { int n; cin >> n; vector<long long> x(n); for (int i = 0; i < n; ++i) { cin >> x[i]; } vector<long long> cnt(61); for (int i = 0; i < n; ++i) { for (int j = 0; j < 61; ++j) { if (x[i] >> j & 1) { cnt[j] ++; } } } long long ans = 0; for (int j = 0; j < n; ++j) { long long sa = 0; for (int b = 0; b < 61; ++b) { if (x[j] >> b & 1) { sa = (sa + (1LL << b) % P * cnt[b] % P) % P; } } long long sb = 0; for (int b = 0; b < 61; ++b) { if (x[j] >> b & 1) { sb = (sb + (1LL << b) % P * n % P) % P; } else { sb = (sb + (1LL << b) % P * cnt[b] % P) % P; } } ans = (ans + sa * sb) % P; } cout << ans << '\n'; } return 0; }