• 2019 Multi-University Training Contest 4


    2019 Multi-University Training Contest 4

    题目链接

    A.AND Minimum Spanning Tree

    贪心连边即可,对于一个数(x),如果其二进制位在低位存在(0),那么就连向最小的(0)的位置;否则就说明(x)(11111)这种形式,如果最高位再加一位在题目范围内就连向它;否则连向(1)即可。

    Code
    #include<bits/stdc++.h>
    typedef long long ll;
    const int MAXN = 2e5 + 5, MAXM = 3e5 + 5, INF = 0x3f3f3f3f, MOD = 998244353;
    const ll INFL = 0x3f3f3f3f3f3f3f3f;
    using namespace std;
    const int oo = (1e9) - (1e6);
    #define lson o<<1,l,m
    #define rson o<<1|1,m+1,r
    #define mid l + ((r-l)>>1)
    #define pb push_back
    #define RR register
    #define random(a,b) ((a)+rand()%((b)-(a)+1))
    #define all(v) (v.begin(),v.end())
    #define lc(x) c[x][0]
    #define rc(x) c[x][1]
    typedef long double db;
    typedef unsigned int uint;
    
    int t, n;
    vector<int> ans;
    int main() {
        ios::sync_with_stdio(false); cin.tie(0);
        cin >> t;
        while (t--) {
            ans.clear();
            cin >> n;
            int m = 1;
            while (m * 2 <= n)m <<= 1;
            int b = 2;
            ll res = 0;
            for (int i = 2; i <= m; i++) {
                if (i > b)b <<= 1;
                bool flag = false;
                for (int j = 0; (1 << j) <= i; j++) {
                    if (!(i >> j & 1)) {
                        ans.push_back(1 << j);
                        flag = true;
                        break;
                    }
                }
                if (!flag)ans.push_back(b);
            }
            for (int i = m + 1; i <= n; i++) {
                bool flag = false;
                for (int j = 0; (1 << j) <= i; j++) {
                    if (!(i >> j & 1)) {
                        ans.push_back(1 << j);
                        flag = true;
                        break;
                    }
                }
                if (!flag)ans.push_back(1), res++;
            }
            cout << res << '
    ';
            for (int i = 0; i < ans.size(); i++)cout << ans[i] << " 
    "[i == ans.size() - 1];
        }
        return 0;
    }
    

    D.Divide the Stones

    手推(frac{n}{k}=1,2,3)的情况,令(t=frac{n}{k}),构造的时候将(t)不断缩小规模就行了。
    注意一下特殊情况的判断。

    Code
    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N = 1e5 +5;
    int T;
    int n, k;
    vector <int> v[N];
    void solve2(int l, int r) {
        for(int i = 1; i <= k; i++) {
            v[i].push_back(l);
            v[i].push_back(r);
            l++; r--;
        }
    }
    void solve3(int l, int r) {
        int tot = (1ll * r * (r + 1) / 2) / k;
        for(int i = 1; i <= k; i++) {
            v[i].push_back(r);
            r--;
        }
        int tmp = 1;
        for(int i = 1; i <= k; i++) {
            v[i].push_back(tmp);
            tmp += 2;
            if(tmp > k) tmp = 2;
        }
        for(int i = 1; i <= k; i++) {
            int sz = v[i].size();
            v[i].push_back(tot - v[i][sz - 1] - v[i][sz - 2]);
        }
    }
    int main() {
        ios::sync_with_stdio(false); cin.tie(0);
        cin >> T;
        while(T--) {
            cin >> n >> k;
            if((1ll * (n + 1) * n / 2) % k != 0) {
                cout << "no" << '
    ';
                continue;
            }
            if(n == k) {
                if(n == 1) cout << "yes" << '
    ' << 1 << '
    ';
                else cout << "no" << '
    ';
                continue;
            }
            for(int i = 1; i <= k; i++) v[i].clear();
            int t = n / k;
            int tmp = t;
            while(tmp > 3) {
                solve2(n - 2 * k + 1, n);
                tmp -= 2;
                n -= 2 * k;
            }
            if(tmp == 3) solve3(1, n);
            else solve2(1, n);
            cout << "yes" << '
    ';
            for(int i = 1; i <= k; i++) {
                for(auto x : v[i]) cout << x << ' ';
                cout << '
    ';
            }
        }
        return 0;
    }
    
    

    G.Just an Old Puzzle

    结论题,跟两种局面下逆序对的奇偶性和行差的奇偶性有关

    Code
    #include<bits/stdc++.h>
    typedef long long ll;
    const int MAXN = 2e5 + 5, MAXM = 3e5 + 5, INF = 0x3f3f3f3f, MOD = 998244353;
    const ll INFL = 0x3f3f3f3f3f3f3f3f;
    using namespace std;
    const int oo = (1e9) - (1e6);
    #define lson o<<1,l,m
    #define rson o<<1|1,m+1,r
    #define mid l + ((r-l)>>1)
    #define pb push_back
    #define RR register
    #define random(a,b) ((a)+rand()%((b)-(a)+1))
    #define all(v) (v.begin(),v.end())
    #define lc(x) c[x][0]
    #define rc(x) c[x][1]
    typedef long double db;
    typedef unsigned int uint;
    
    int t, a;
    vector<int> v;
    int main() {
        ios::sync_with_stdio(false); cin.tie(0);
        cin >> t;
        while (t--) {
            v.clear();
            int r = 0;
            for (int i = 1; i <= 4; i++) {
                for (int j = 1; j <= 4; j++) {
                    cin >> a;
                    if (a)v.push_back(a);
                    else r = i;
                }
            }
            r = 4 - r;
            int d = 0;
            for (int i = 0; i < 15; i++) {
                for (int j = i + 1; j < 15; j++) {
                    if (v[j] < v[i])d ^= 1;
                }
            }
            r %= 2;
            if (!(d^r))cout << "Yes
    ";
            else cout << "No
    ";
        }
        return 0;
    }
    

    H.K-th Closest Distance

    一开始被(k)的范围坑了,直接(T)飞= =
    注意等价条件,如果一个(p)(x)的距离为第(k)大,那么(|p-x|,|p+x|)这个区间范围有(k)个数。
    然后二分就行了。
    代码如下:

    Code
    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N = 2e5 + 5;
    int T;
    int a[N], b[N];
    int n, m;
    int rt[N], sum[N * 20], ls[N * 20], rs[N * 20];
    int tot;
    void build(int &o, int l, int r) {
        o = ++tot;
        sum[o] = 0;
        if(l == r) return ;
        int mid = (l + r) >> 1;
        build(ls[o], l, mid); build(rs[o], mid + 1, r);
    }
    void insert(int last, int &o, int l, int r, int v) {
        o = ++tot;
        ls[o] = ls[last]; rs[o] = rs[last];
        sum[o] = sum[last] + 1;
        if(l == r) return;
        int mid = (l + r) >> 1;
        if(v <= mid) insert(ls[last], ls[o], l, mid, v);
        else insert(rs[last], rs[o], mid + 1, r, v);
    }
    int query(int last, int o, int l, int r, int L, int R) {
        if(L <= l && r <= R) return sum[o] - sum[last];
        int mid = (l + r) >> 1, ans = 0;
        if(L <= mid) ans += query(ls[last], ls[o], l, mid, L, R);
        if(R > mid) ans += query(rs[last], rs[o], mid + 1, r, L, R);
        return ans;
    }
    int main() {
        ios::sync_with_stdio(false); cin.tie(0);
        cin >> T;
        while(T--) {
            cin >> n >> m;
            for(int i = 1; i <= n; i++) cin >> a[i], b[i] = a[i];
            sort(b + 1, b + n + 1);
            int D = unique(b + 1, b + n + 1) - b - 1;
            for(int i = 1; i <= n; i++) a[i] = lower_bound(b + 1, b + D + 1, a[i]) - b;
            tot = 0; build(rt[0], 1, D);
            for(int i = 1; i <= n; i++) insert(rt[i - 1], rt[i], 1, D, a[i]);
            int last = 0;
            while(m--) {
                int l, r, p, k; cin >> l >> r >> p >> k;
                l ^= last; r ^= last; p ^= last; k ^= last;
                int L = 0, R = 1e6 + 1, mid;
                while(L < R) {
                    mid = (L + R) >> 1;
                    int k1 = lower_bound(b + 1, b + n + 1, p - mid) - b;
                    int k2 = upper_bound(b + 1, b + n + 1, p + mid) - b - 1;
                    if(query(rt[l - 1], rt[r], 1, D, k1, k2) >= k) R = mid;
                    else L = mid + 1;
                }
                last = R; cout << last << '
    ';
            }
        }
        return 0;
    }
    

    J.Minimal Power of Prime

    暴力筛去(4000)以内的素数,那么最终将(n)分解质因子指数和不会超过(4)
    考虑各种情况的答案,答案为(4)时,就是(p^4)的形式;答案为(3)时,就是(p^3);答案为(2)时,就是(p^2q^2);答案为(1)时就是其它情况。
    然后对于这三种直接开方判断就行,注意一下顺序就行了。
    (pow)的时候加个(round)会减小误差。
    代码如下:

    Code
    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N = 4001;
    bool vis[N];
    int prime[N], tot;
    void pre() {
        for(int i = 2; i < N; i++) {
            if(!vis[i]) {
                prime[++tot] = i;
                for(int j = i * i; j < N; j += i) vis[j] = 1;
            }
        }
    }
    int T;
    ll n;
    int main() {
        ios::sync_with_stdio(false); cin.tie(0);
        pre();
        cin >> T;
        while(T--) {
            cin >> n;
            int ans = 100;
            for(int i = 1; i <= tot; i++) {
                if(n % prime[i] == 0) {
                    int cnt = 0;
                    while(n % prime[i] == 0) cnt++, n /= prime[i];
                    if(cnt) ans = min(ans, cnt);
                }
            }
            ll a = round(pow(n, 1 / 4.0));
            ll b = round(pow(n, 1 / 3.0));
            ll c = round(pow(n, 1 / 2.0));
            if(a > 1 && a * a * a * a == n) ans = min(ans, 4);
            else if(b > 1 && b * b * b == n) ans = min(ans, 3);
            else if(c > 1 && c * c == n) ans = min(ans, 2);
            else if(n > 1) ans = 1;
            cout << ans << '
    ';
        }
        return 0;
    }
    
  • 相关阅读:
    Elasticsearch 内存配置应用案例
    shell进阶篇之字典和数组结合应用案例
    shell进阶篇之数组应用案例
    nginx的负载均衡
    nginx的反向代理
    ajax的几种使用
    springboot整合Redis
    java的Spring中@Value注解的使用
    Redis的五种数据类型
    冒泡排序
  • 原文地址:https://www.cnblogs.com/heyuhhh/p/11281642.html
Copyright © 2020-2023  润新知