2020 CCPC Henan

A. 班委竞选

签到题

#include <bits/stdc++.h>

using namespace std;

int32_t main() {
    int n , m ;
    cin >> n >> m;
    vector<int> a( m+1 , 0 ) , b( m+1 , 0 );
    for( int i = 1 , c , t ; i <= n ; i ++ ){
        cin >> c >> t;
        if( t > a[c] ) a[c] = t , b[c] = i;
    }
    for( int i = 1 ; i <= m ; i ++ )
        cout << b[i] << " ";
    return 0;
}

C. 我得重新集结部队

\(n\le 2\times 10^2\),所以直接\(O(n^2)\)的遍历就好了,如果是异虫直接加入队列,如果是狂热者先找出离他最近的传送过去,然后在暴力处理攻击范围内的虫即可

#include <bits/stdc++.h>

using namespace std;

#define int long long

int read() {
    int x = 0, f = 1, ch = getchar();
    while ((ch < '0' || ch > '9') && ch != '-') ch = getchar();
    if (ch == '-') f = -1, ch = getchar();
    while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
    return x * f;
}

int32_t main() {
    int n = read();
    vector<int> res;
    vector<tuple<int, int, int> > g;
    for (int opt, x, y, a, b; n; n--) {
        opt = read(), x = read(), y = read(), a = read();
        if (opt == 1) g.emplace_back(x, y, a), res.push_back(g.size() - 1);
        else {
            a *= 3ll, b = read(), b = b * b;
            int d = LLONG_MAX, dx, dy, t;
            for (auto [r, c, h]: g) {
                if (h <= 0) continue;
                t = (r - x) * (r - x) + (c - y) * (c - y);
                if (t < d) d = t, dx = r, dy = c;
            }
            x = dx, y = dy, t = -1;
            for (auto &[r, c, h]: g) {
                if (h <= 0) continue;
                d = (r - x) * (r - x) + (c - y) * (c - y);
                if( d <= b ){
                    h -= a;
                    if( h > 0ll ) t = -2;
                }
            }
            res.push_back(t);
        }
    }
    for( auto i : res )
        if( i < 0 ){
            if( i == -1 ) cout << "Yes\n";
            else cout << "No\n";
        }else{
            if( get<2>(g[i]) > 0 ) cout << "Yes\n";
            else cout << "No\n";
        }
    return 0;
}

E. 发通知

树状数组也是可以维护异或和的。先把\(a,b+1\)全部离散化,然后用一个数组维护每个时刻能够通知的数量,再用一个树状数组维护每个时刻的异或和即可。复杂度\(O(n\log n)\)

#include <bits/stdc++.h>

using namespace std;

class bit {
private:
    int n;
    vector<int> b;

    int lowbit(int x) {
        return (x & -x);
    }

public:
    bit(int n) : n(n) {
        b = vector<int>(n + 1);
    }

    void add(int x, int val) {
        for (int i = x; i <= n; i += lowbit(i))
            b[i] += val;
        return;
    }

    int getV(int x) {
        int res = 0;
        for (int i = x; i; i -= lowbit(i))
            res += b[i];
        return res;
    }
};

class bit2 {
private:
    int n;
    vector<int> b;

    int lowbit(int x) {
        return (x & -x);
    }

public:
    bit2(int n) : n(n) {
        b = vector<int>(n + 1);
    }

    void add(int x, int val) {
        for (int i = x; i <= n; i += lowbit(i))
            b[i] ^= val;
        return;
    }

    int getV(int x) {
        int res = 0;
        for (int i = x; i; i -= lowbit(i))
            res ^= b[i];
        return res;
    }
};

int read() {
    int x = 0, f = 1, ch = getchar();
    while ((ch < '0' || ch > '9') && ch != '-') ch = getchar();
    if (ch == '-') f = -1, ch = getchar();
    while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
    return x * f;
}

int main() {
    int n = read(), k = read();
    vector<tuple<int, int, int> > a(n);
    vector<int> b;
    for (auto &[l, r, w]: a) l = read(), r = read()+1, w = read(), b.push_back(l), b.push_back(r);
    sort(b.begin(), b.end());
    auto t = unique(b.begin(), b.end())++;
    int m = t - b.begin() + 5;
    bit p(m);
    bit2 q(m);
    for (auto &[l, r, w]: a) {
        l = lower_bound(b.begin(), t, l) - b.begin() + 1;
        r = lower_bound(b.begin(), t, r) - b.begin() + 1;
        p.add(l, 1), p.add(r, -1);
        q.add(l, w), q.add(r, w);
    }
    int res = -1;
    for( int i = 1 ; i < m ; i ++ ){
        if( p.getV(i) < k ) continue;
        res = max( res , q.getV(i) );
    }
    cout << res;
    return 0;
}

I. 太阳轰炸

一道不太难的数学题

首先命中的概率是\(p=\min( 1 , (\frac{R_1+r}{R_2})^2)\),然后要击毁至少要命中$k=\left \lceil \frac{h}{a} \right \rceil $,根据二项式定理可知答案是

\[\sum_{i=k}^{k} C_n^i p^i(1-p)^{n-i} \]

注意取模就好了

#include <bits/stdc++.h>

using namespace std;

#define int long long

const int mod = 1e9 + 7;

int power(int x, int y) {
    x = x % mod;
    int ans = 1;
    while (y) {
        if (y & 1) ans = ans * x % mod;
        y >>= 1, x = x * x % mod;
    }
    return ans;
}

int inv(int x) {
    return power(x, mod - 2);
}

vector<int> fact, invFact;

void init(int n) {
    fact = vector<int>(n + 1), invFact = vector<int>(n + 1);
    fact[0] = 1, invFact[0] = inv(1);
    for (int i = 1; i <= n; i++)
        fact[i] = fact[i - 1] * i % mod, invFact[i] = inv(fact[i]);
    return;
}

int C(int x, int y) {
    return fact[x] * invFact[x - y] % mod * invFact[y] % mod;
}

int32_t main() {
    int n, r1, r2, r, a, h;
    cin >> n >> r1 >> r2 >> r >> a >> h;
    init(n);

    if (r1 + r >= r2) return cout << 1, 0;
    int p, q;
    p = (r1 + r) * inv(r2) % mod, p = p * p % mod, q = ((1 - p) % mod + mod) % mod;
    int invQ = inv(q);
    int res = 0;
    for (int i = (h + a - 1) / a , s = power( p , i ) , t = power( q , n - i ) ; i <= n; i++)
        res = (res + C(n, i) * s % mod * t % mod ) % mod , s = s * p % mod , t = t * invQ % mod;
    cout << res;

    return 0;
}
posted @ 2023-02-15 21:15  PHarr  阅读(33)  评论(0编辑  收藏  举报