Codeforces Round #716 (Div. 2)

Codeforces Round #716 (Div. 2)

A - Perfectly Imperfect Array

int main() {
    IOS;
    for (cin >> _; _; --_) {
        cin >> n; bool f = 0;
        rep (i, 1, n) {
            cin >> m; k = sqrt(m);
            if (k * k != m) f = 1;
        }
        cout << (f ? "YES\n" : "NO\n");
    }
    return 0;
}

B - AND 0, Sum Big

要求和最大且 & 为 0,则在二进制(\(0~k-1\))每个位置在序列种都有一个为的这一位为\(0\)

组合数, 用不用快速幂都行,\(k \leqslant 20\)

ll qpow(ll a, ll b) {
    ll ans = 1;
    for (; b; b >>= 1, a = a * a % mod) if (b & 1) ans = ans * a % mod;
    return ans;
}
 
int main() {
    IOS;
    for (cin >> _; _; --_) {
        cin >> n >> k;
        cout << qpow(n, k) << '\n';
    }
    return 0;
}

C - Product 1 Modulo N

这题怎么招也该D吧,数论下手

设乘积为\(x\), 则$gcd(x, n) = gcd(k \times n + 1, n) = 1 $ 故乘积互质

在把剩下的数相乘得到\(x = k \times n + d\)

先证明一下答案肯定存在

不存在题目该说-1

这明显是个模\(n\)单目运算为乘法的群, 必然存在乘模运算结果为\(1\) (离散数学)

\(x = d \times (\frac{k}{d} \times n + 1) = k \times n + d, d < n\)

所以我们把剩下的与\(n\)互质的数中的\(d, 1 < d\)扔了就好

int main() {
    IOS; cin >> n; set<int> st; ll c = 1;
    rep (i, 1, n - 1) if (__gcd(i, n) == 1) st.insert(i), c = c * i % n;
    st.erase(c % n); st.insert(1);
    cout << st.size() << '\n'; for (auto &i : st) cout << i << ' ';
    return 0;
}

D - Cut and Stick

(莫队的题解在下面)

注意到一段最多有一个数频率高于阈值, 出现\(c\) 次, 长度为\(len\)

则分成\(c - (len - c) = 2 \times c - len\)

然后就是怎么求区间众数了

注意到区间长为\(len\), 众数至少出现\(\left \lceil \frac{n}{2} \right \rceil\)

我们随机选取\([l, r]\)中的一个数, 通过二分求其出现的次数, 随机40次

随机不到众数的概率为\((\frac{n - \left \lceil \frac{n}{2} \right \rceil}{n})^{40} = 2^{-40}\)

还记得那个\(0.9^{365}\), 这个同理, 随机不到众数的概率极其低下, 可认为能随机到众数

int main() {
    IOS; cin >> n >> m;
    rep (i, 1, n) cin >> a[i], st[a[i]].pb(i);
    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
    rep (i, 1, m) {
        int l, r, c = 0; cin >> l >> r;
        rep (j, 1, 40) {
            int d = a[uniform_int_distribution<int>(l,r)(rng)];
            umax(c, upper_bound(all(st[d]), r) - lower_bound(all(st[d]), l));
        }
        cout << max(1, 2 * c - r + l - 1) << '\n';
    }
    return 0;
}

莫队, 没啥好讲的, 思路和上面一样, 莫队求区间众数

struct Q { int l, r, id; } q[N];

int n, m, _, k, cas;
int a[N], id[N], s[N], c[N], len, mx, l = 1, r;

void add(int x) { --s[c[a[x]]]; umax(mx, ++c[a[x]]); ++s[c[a[x]]]; }

void sub(int x) { --s[c[a[x]]]; if (!s[mx]) --mx; ++s[--c[a[x]]]; }

int main() {
    IOS; cin >> n >> m; len = sqrt(n); s[0] = n;
    rep (i, 1, n) cin >> a[i], id[i] = i / len;
    rep (i, 1, m) cin >> q[i].l >> q[i].r, q[i].id = i;
    sort(q + 1, q + 1 + m, [&](Q& a, Q& b) { return id[a.l] ^ id[b.l] ? a.l < b.l : a.r < b.r; });
    rep (i, 1, m) {
        while (r < q[i].r) add(++r);
        while (l < q[i].l) sub(l++);
        while (l > q[i].l) add(--l);
        while (r > q[i].r) sub(r--);
        id[q[i].id] = max(1, 2 * mx - q[i].r + q[i].l - 1);
    }
    rep (i, 1, m) cout << id[i] << '\n';
    return 0;  
}

Baby Ehab's Hyper Apartment

posted @ 2021-04-21 00:26  洛绫璃  阅读(81)  评论(0编辑  收藏  举报