• 2021牛客暑期多校训练营1


    2021牛客暑期多校训练营1

    A - Alice and Bob

    由必败态去把其他状态推出来, 其实只记录必败态就行了

    #include <bits/stdc++.h>
    using namespace std;
    
    int main() {
        vector<vector<bool>> f(5001, vector<bool>(5001));
        for (int i=0; i <= 5000;++ i)
            for (int j = 0; j <= i; ++j)
                if (!f[i][j])
                    for (int k = 1; k + min(i,j) <= 5000; ++k)
                        for(int s = 0; s + min(i,j) <= 5000; s += k) {
                            int dx = i + k, dy = j + s;
                            if (max(dx, dy) <= 5000)
                                f[max(dx, dy)][min(dx, dy)]=1;
                            dx = i + s, dy = j + k;
                            if (max(dx, dy) <= 5000)
                                f[max(dx, dy)][min(dx, dy)]=1;
                        }
        int _;
        for (cin >> _; _; --_) {
            int n, m;
            cin >> n >> m;
            cout << (f[max(n, m)][min(m, n)] ? "Alice" : "Bob") << '
    ';
        }
        return 0;
    }
    

    B - Ball Dropping

    初中平面几何,做几条辅助线就出来了

    看图找找相似三角形, 求求三角函数就算出来了

    int main() {
        IOS;
        double r, a, b, h;
        cin >> r >> a >> b >> h;
        if (b - r * 2 >= 0)
            return cout << "Drop", 0;
        cout << "Stuck
    ";
        double l = sqrt(h * h +sqr((a - b) / 2));
        double cur = (h * a / 2 - r * h * h / l) * 2  / (a - b);
        cout << precision(10) << h + r * ((a - b) / 2 / l) - cur;
        return 0;
    }
    

    D - Determine the Photo Position

    int main() {
        int n, m;
        cin >> n >> m;
        vector<string> a(n);
        for (auto &i : a)
            cin >> i;
    
        string b;
        cin >> b;
    
        long long ans = 0;
        for (auto &s : a)
            for (int i = 0, j = 0; i < s.size(); i = ++j)
                if (s[i] == '0') {
                    while (j < s.size() && s[j] == '0')
                        ++j;
                    ans += max(0, (int)(j - i + 1 - b.size()));
                }
        cout << ans;
        return 0;
    }
    

    F - Find 3-friendly Integers

    对于任意三个数,总有办法拼出3的倍数

    暴力求100以内的个数即可

    vector<int> sum(100);
    
    void init() {
        for (int i = sum[0] = 1; i < 100; ++i) {
            bool f = 0;
            if (i % 10 % 3 == 0)
                f = 1;
            else if (i >= 10)
                if (i / 10 % 3 == 0)
                    f = 1;
                else if ((i / 10 + i % 10) % 3 == 0)
                   f = 1;
            sum[i] = sum[i - 1] + f;
        }
    }
    
    long long ask(long long n) {
        return n < 100 ? sum[n] : sum[99] + n - 99;
    }
    
    int main() {
        init();
        int _;
        for (cin >> _; _; --_) {
            long long l, r;
            cin >> l >> r;
            cout << ask(r) - ask(l - 1) << '
    ';
        }
        return 0;
    }
    

    G - Game of Swapping Numbers

    考虑把(a_i, b_i) 映射到数轴上, 则最后求的是n个线段的长度,

    对于交换(a_i, a_j), 只有当线段(i, j) 不重合时才能有贡献, 且贡献为两个线段的距离的两倍(画个图就明白了)

    (max(a_i, b_j) < min(a_j, b_j)) 交换后增加的贡献为 ((min(a_j, b_j) - max(a_i, b_j)) * 2)

    (n = 2)时, 只能交换(1, 2)

    (n > 2)时,必定存在两个线段(a_i - b_i > 0, a_j - b_j > 0)(a_i - b_i < 0, a_j - b_j < 0) 及这两个线段交换不会对答案产生影响, 及我们可以浪费交换次数

    我们直接另(mx_i = max(a_i, b_i), mi_i = min(a_i, b_i)) 然后排序求差只算正的贡献即可

    int main() {
        ios::sync_with_stdio(0);
        cin.tie(0), cout.tie(0);
    
        int n, k;
        cin >> n >> k;
        vector<int> a(n), b(n);
        for (auto &i : a) cin >> i;
        for (auto &i : b) cin >> i;
        if (n == 2) {
            if (k & 1) swap(a[1], a[0]);
            cout << abs(a[0] - b[0]) + abs(a[1] - b[1]);
            return 0;
        }
    
        long long ans = 0;
        for (int i = 0; i < n; ++i) {
            ans += abs(a[i] - b[i]);
            if (a[i] < b[i]) swap(a[i], b[i]);
        }
        sort(a.begin(), a.end(), greater<int>());
        sort(b.begin(), b.end());
        for (int i = 0; i < min(k, n); ++i)
            ans += max(0, a[i] - b[i]);
        cout << ans;
        return 0;
    }
    

    H - Hash Function

    首先发现模数不能使任意两个数的差的因子,但任意两数差就已经(O(n^2))

    考虑ftt,将求差变为多项式相乘

    多项式相加都可以通过

    (x_i ± x_j, A^{x_i} imes A^{±x_j} = A^{x_i ± x_j})

    这样就可以用ftt加速, 优化到(nlogn)

    对指数加个偏移量就可以防止指数出现负数

    const double PI = acos(-1.0);
    struct Complex {
        double x, y;
        Complex(double _x = 0.0, double _y = 0.0) {
            x = _x;
            y = _y;
        }
        Complex operator-(const Complex &b) const {
            return Complex(x - b.x, y - b.y);
        }
        Complex operator+(const Complex &b) const {
            return Complex(x + b.x, y + b.y);
        }
        Complex operator*(const Complex &b) const {
            return Complex(x * b.x - y * b.y, x * b.y + y * b.x);
        }
    };
    /*
     * 进行 FFT 和 IFFT 前的反置变换
     * 位置 i 和 i 的二进制反转后的位置互换
     * len 必须为 2 的幂
     */
    void change(Complex y[], int len) {
        vector<int> rev(len);
        for (int i = 0; i < len; ++i) {
            rev[i] = rev[i >> 1] >> 1;
            if (i & 1)  // 如果最后一位是 1,则翻转成 len/2
                rev[i] |= len >> 1;
        }
        for (int i = 0; i < len; ++i)
            if (i < rev[i])  // 保证每对数只翻转一次
                swap(y[i], y[rev[i]]);
    }
    /*
     * 做 FFT
     * len 必须是 2^k 形式
     * on == 1 时是 DFT,on == -1 时是 IDFT
     */
    void fft(Complex y[], int len, int on) {
        change(y, len);
        for (int h = 2; h <= len; h <<= 1) {
            Complex wn(cos(2 * PI / h), sin(on * 2 * PI / h));
            for (int j = 0; j < len; j += h) {
                Complex w(1, 0);
                for (int k = j; k < j + h / 2; ++k) {
                    Complex u = y[k], t = w * y[k + h / 2];
                    y[k] = u + t;
                    y[k + h / 2] = u - t;
                    //模长相乘,辅角相加,模长为1相乘不变,相当于辅角增加了2 * PI / h
                    w = w * wn;
                }
            }
        }
        if (on == -1)
            for (int i = 0; i < len; ++i)
                y[i].x /= len;
    }
     
    const int N = 5e5 + 5;
    Complex x1[N << 2], x2[N << 2], x3[N << 2];
    int n;
    bool v[N];
     
    int main() {
        ios::sync_with_stdio(0);
        cin.tie(0), cout.tie(0);
     
        cin >> n;
        if (n == 1) return cout << 1, 0;
        int len = 1 << int(log2(1e6) + 1);
        for (int i = 0; i < len; ++i)
            x1[i] = x2[i] = Complex(0, 0);
        for (int i = 0; i < n; ++i) {
            int x; cin >> x;
            x1[x] = Complex(1, 0);
            x2[500000 - x] = Complex(1, 0);
        }
        fft(x1, len, 1);
        fft(x2, len, 1);
        for (int i = 0; i < len; ++i)
            x3[i] = x1[i] * x2[i];
        fft(x3, len, -1);
        for (int i = 1; i <= 500000; ++i)
            v[i] = int(x3[i + 500000].x + 0.5);
        for (int i = 2; i <= 500001; ++i) {
            int now = i;
            for (int j = i; j <= 500001; j += i)
                if (v[j]) now = -1;
            if (~now)
                return cout << now, 0;
        }
        return 0;
    }
    

    K - Knowledge Test about Match

    纯靠猜, 瞎贪心

       for (cin >> _; _; --_) {
            cin >> n;
            VI cnt(n), a(n, -1);
            for (int i = 0; i < n; ++i) {
                int x; cin >> x;
                ++cnt[x];
            }
            for (int i = 0; i < n; ++i)
                for (int j = 0; j < n; ++j)
                    if (~a[j]) continue;
                    else if (j + i < n && cnt[j + i])
                        --cnt[j + i], a[j] = j + i;
                    else if (j - i > -1 && cnt[j - i])
                        --cnt[j - i], a[j] = j - i;
            for (int i = 0; i < n; ++i) 
                cout << a[i] << char(" 
    "[i == n - 1]);
        }
    
  • 相关阅读:
    mysql case when用法
    php+mysql实现事务回滚
    go安装windows源码
    【C++】子类访问父类typedef的问题
    【C++】STL算法之remove_if
    MySQL常用函数总结
    Apriori算法+python实现
    数据库索引理论
    Linux基本命令
    JAVA 多线程
  • 原文地址:https://www.cnblogs.com/2aptx4869/p/15025278.html
Copyright © 2020-2023  润新知