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';
  }
}
View Code

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;
}
View Code

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];
  }
}
View Code

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;
}
View Code

 

posted @ 2021-07-29 21:34  19992147  阅读(47)  评论(0编辑  收藏  举报