zoukankan      html  css  js  c++  java
  • Educational Codeforces Round 78 (Rated for Div. 2)

    传送门

    A. Shuffle Hashing

    签到。

    Code
    /*
     * Author:  heyuhhh
     * Created Time:  2019/12/21 10:03:44
     */
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <vector>
    #include <cmath>
    #include <set>
    #include <map>
    #include <queue>
    #include <iomanip>
    #define MP make_pair
    #define fi first
    #define se second
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    #define INF 0x3f3f3f3f
    #define Local
    #ifdef Local
      #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
      void err() { std::cout << '
    '; }
      template<typename T, typename...Args>
      void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
    #else
      #define dbg(...)
    #endif
    void pt() {std::cout << '
    '; }
    template<typename T, typename...Args>
    void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    //head
    const int N = 100 + 5;
     
    char s[N], t[N];
     
    int pre[26];
    int sum[N][26];
     
    void run(){
        memset(pre, 0, sizeof(pre));
        cin >> (s + 1) >> (t + 1);
        int n = strlen(s + 1);
        for(int i = 1; i <= n; i++) ++pre[s[i] - 'a'];
        int m = strlen(t + 1);
        for(int i = 1; i <= m; i++) {
            for(int j = 0; j < 26; j++) sum[i][j] = sum[i - 1][j];
            ++sum[i][t[i] - 'a'];   
        }
        for(int i = 1; i <= m; i++) {
            for(int j = i; j <= m; j++) {
                static int cnt[26];
                for(int k = 0; k < 26; k++) cnt[k] = sum[j][k] - sum[i - 1][k];
                bool flag = false;
                for(int k = 0; k < 26; k++) {
                    if(cnt[k] != pre[k]) flag = true;
                }       
                if(flag == false) {
                    cout << "YES" << '
    ';
                    return;   
                }
            }
        }
        cout << "NO" << '
    ';
    }
     
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
        int T; cin >> T;
        while(T--) run();
        return 0;
    }
    

    B. A and B

    先全部加到较小的一方,然后考虑怎么取出一部分填另一方使得两者相等。

    C. Berry Jam

    题意:
    现在有(2n)个糖果,每个糖果有红蓝两者颜色。
    现在你位于中间的位置,左边(n)个糖果,右边(n)个糖果。每次只能吃连续的一段糖果。
    现在回答最少吃多少个糖果,能使得剩下的糖果红蓝两种颜色的数量相等。

    思路:

    • 考虑枚举一半,然后快速在另一半中找到答案。
    • 假设我们用((x,y))表示红蓝两种颜色的数量,容易发现(x,y)的变化是连续的。
    • 假设我们目前枚举到了(i),并且将(n+1)~(i)的糖果都吃完,分别剩下(r,b)红、蓝糖果。
    • (r>b),那么就需要找到第一次(d=r-b)的位置,(d=x-y);否则,就需要找到第一次(d=b-r)的位置,(d=y-x)
    • 那么事先从(n)(1)扫一遍,存储一下第一次出现的位置即可。
    • 另外要记得排除一些特殊情况,比如只吃左半部分的糖果这种以及一个糖果都不吃。
    • 时间复杂度(O(n))

    代码如下:

    Code
    /*
     * Author:  heyuhhh
     * Created Time:  2019/12/21 10:16:12
     */
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <vector>
    #include <cmath>
    #include <set>
    #include <map>
    #include <queue>
    #include <iomanip>
    #define MP make_pair
    #define fi first
    #define se second
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    #define INF 0x3f3f3f3f
    #define Local
    #ifdef Local
      #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
      void err() { std::cout << '
    '; }
      template<typename T, typename...Args>
      void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
    #else
      #define dbg(...)
    #endif
    void pt() {std::cout << '
    '; }
    template<typename T, typename...Args>
    void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    //head
    const int N = 2e5 + 5;
     
    int n;
    int a[N];
    int x[N], y[N];
    int q[N], top;
    int q2[N], top2;
     
    int find(int A, int B) {
        if(A == B) return n + 1;
        if(A > B) return q2[A - B];
        return q[B - A];
    }
     
    void run(){
        cin >> n;
        top = top2 = 0; 
        for(int i = 1; i <= 2 * n; i++) q[i] = q2[i] = 0;
        for(int i = 1; i <= 2 * n; i++) cin >> a[i];
        int r = 0, b = 0;
        for(int i = 1; i <= 2 * n; i++) {
            if(a[i] == 1) ++r; else ++b;
        }
        x[n + 1] = y[n + 1] = 0;
        for(int i = n; i >= 1; i--) {
            x[i] = x[i + 1]; y[i] = y[i + 1];   
            if(a[i] == 1) ++x[i]; else ++y[i];
            if(x[i] - y[i] > x[q2[top2]] - y[q2[top2]]) q2[++top2] = i;
            if(y[i] - x[i] > y[q[top]] - x[q[top]]) q[++top] = i;
        }
        int ans = 2 * n;
        int curr = 0, curb = 0;
        for(int i = n + 1; i <= 2 * n; i++) {
            if(a[i] == 1) ++curr;
            else ++curb;
            int nr = r - curr, nb = b - curb;
            int p = find(nr, nb);
            if(p) ans = min(ans, i - p + 1);
        }
        curr = curb = 0;
        for(int i = n; i >= 1; i--) {
            if(a[i] == 1) ++curr;
            else ++curb;
            if(r - curr == b - curb) {
                ans = min(ans, n - i + 1);   
            }
        }
        if(r == b) ans = 0;
        cout << ans << '
    ';
    }
     
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
        int T; cin >> T;
        while(T--) run();
        return 0;
    }
    

    D. Segment Tree

    题意:
    给出(n)个区间,每个区间坐标范围为([1,2n]),并且保证区间起点终点互不相等。
    现在若存在两个区间相交(不包含、包含不算),那么对应的点将会有一条边。
    现在判断最终(n)个点形成的图是否为一棵树。

    思路:
    对于树的判定,我们只要保证图连通且有(n-1)条边即可。
    这一条件等价于存在(n-1)条边并且没有环。
    那么我们用并查集维护点之间的关系,同时判断一下是否存在环即可。
    一开始直接将当前区间和(set)中的元素进行合并,T了。之后发现其实左端点在当前区间左边的区间无用,所以直接二分到相交的区间合并即可。
    因为至多会合并(n)次,所以复杂度为(O(nlogn))

    Code
    /*
     * Author:  heyuhhh
     * Created Time:  2019/12/21 11:16:58
     */
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <vector>
    #include <cmath>
    #include <set>
    #include <map>
    #include <queue>
    #include <iomanip>
    #define MP make_pair
    #define fi first
    #define se second
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    #define INF 0x3f3f3f3f
    #define Local
    #ifdef Local
      #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
      void err() { std::cout << '
    '; }
      template<typename T, typename...Args>
      void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
    #else
      #define dbg(...)
    #endif
    void pt() {std::cout << '
    '; }
    template<typename T, typename...Args>
    void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    //head
    const int N = 1e6 + 5;
     
    int L[N], R[N];
    struct seg {
        int l, r;   
        bool operator < (const seg &A) const {
            return l < A.l;
        }
    }a[N];
    int n, tot;
    set <pii> s;
    int f[N];
    int find(int x) {return f[x] == x ? f[x] : f[x] = find(f[x]);}
    int Union(int x, int l) {
        int res = 0;
        auto p = s.lower_bound(MP(l, 0));
        while(p != s.end()) {
            int y = p -> second;
            int fx = find(x), fy = find(y);
            if(fx == fy) return -1;
            f[fx] = fy;        
            if(++tot >= n) return -1;
            ++p;
        }
        return 1;
    }
     
    void run(){
        for(int i = 1; i <= 2 * n; i++) f[i] = i;
        for(int i = 1; i <= n; i++) cin >> a[i].l >> a[i].r;
        for(int i = 1; i <= n; i++) L[a[i].l] = R[a[i].r] = i;
        for(int i = 1; i < N; i++) {
            if(L[i]) s.insert(MP(a[L[i]].l, L[i]));
            if(R[i]) {
                int id = R[i];
                s.erase(MP(a[id].l, id));
                int t = Union(id, a[id].l);
                if(t == -1) {
                    cout << "NO" << '
    ';
                    return;   
                }
            }
        }
        if(tot == n - 1) cout << "YES" << '
    ';
        else cout << "NO" << '
    ';
    }
     
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
        while(cin >> n) run();
        return 0;
    }
    

    E. Tests for problem D

    题意:
    给出一棵树,要构造出对应的(n)个区间,使得满足D题的条件(就是给D造数据)。

    思路:

    • 先确定儿子的左端点,然后即可确定当前结点的右端点。
    • 之后递归下去依次处理。

    就没了...
    但直接这样没能保证儿子之间互不相交。
    观察到确定左端点时是从左到右逐个确定,那么确定右端点时我们从右往左逐个确定,就能使得儿子区间互相包含了。
    细节详见代码:

    Code
    /*
     * Author:  heyuhhh
     * Created Time:  2019/12/22 16:21:48
     */
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <vector>
    #include <cmath>
    #include <set>
    #include <map>
    #include <queue>
    #include <iomanip>
    #define MP make_pair
    #define fi first
    #define se second
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    #define INF 0x3f3f3f3f
    #define Local
    #ifdef Local
      #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
      void err() { std::cout << '
    '; }
      template<typename T, typename...Args>
      void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
    #else
      #define dbg(...)
    #endif
    void pt() {std::cout << '
    '; }
    template<typename T, typename...Args>
    void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    //head
    const int N = 1e6 + 5;
     
    vector <int> G[N];
     
    int n;
    int L[N], R[N];
    int tot;
     
    void dfs(int u, int fa) {
        for(auto v : G[u]) if(v != fa) {
            L[v] = ++tot;
        }   
        R[u] = ++tot;
        for(int i = sz(G[u]) - 1; i >= 0; i--) {
            int v = G[u][i];
            if(v != fa) dfs(v, u);
        }
    }
     
    void run(){
        for(int i = 1; i < n; i++) {
            int u, v; cin >> u >> v;
            G[u].push_back(v);
            G[v].push_back(u);   
        }
        L[1] = ++tot;
        dfs(1, 0);
        for(int i = 1; i <= n; i++) {
            cout << L[i] << ' ' << R[i] << '
    ';   
        }
    }
     
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
        while(cin >> n) run();
        return 0;
    }
    

    F. Cards

    题意:

    [sum_{i=0}^n{nchoose i}P^i(1-P)^{n-i}i^k ]

    其中(P=frac{1}{m},nleq 10^9,kleq 5000)

    思路:
    直接用第二类斯特拉数将幂次展开并化简:

    [egin{aligned} &sum_{i=0}^n{nchoose i}P^i(1-P)^{n-i}i^k\ =&sum_{i=0}^n{nchoose i}P^i(1-P)^{n-i}sum_{j=0}^k{ichoose j}j!egin{Bmatrix} k \ j end{Bmatrix}\ =&sum_{j=0}^kegin{Bmatrix} k \ j end{Bmatrix}j!sum_{i=0}^n{nchoose i}{ichoose j}P^i(1-P)^{n-i}\ =&sum_{j=0}^kegin{Bmatrix} k \ j end{Bmatrix}j!{nchoose j}sum_{i=0}^n{n-jchoose i-j}P^i(1-P)^{n-i}\ =&sum_{j=0}^kegin{Bmatrix} k \ j end{Bmatrix}j!{nchoose j}P^jsum_{i=0}^{n-j}{n-jchoose i}P^i(1-P)^{n-i-j}\ =&sum_{j=0}^kegin{Bmatrix} k \ j end{Bmatrix}j!{nchoose j}P^j end{aligned} ]

    前面都是套路,最后两步较为巧妙,变换求和范围过后将乘积的形式化为了二项式定理展开的形式,然后直接将和式化简。
    之后我们需要做的就是直接预处理第二类斯特林数即可。
    代码如下:

    Code
    /*
     * Author:  heyuhhh
     * Created Time:  2019/12/21 12:40:57
     */
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <vector>
    #include <cmath>
    #include <set>
    #include <map>
    #include <queue>
    #include <iomanip>
    #define MP make_pair
    #define fi first
    #define se second
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    #define INF 0x3f3f3f3f
    #define Local
    #ifdef Local
      #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
      void err() { std::cout << '
    '; }
      template<typename T, typename...Args>
      void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
    #else
      #define dbg(...)
    #endif
    void pt() {std::cout << '
    '; }
    template<typename T, typename...Args>
    void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    //head
    const int N = 5005, MOD = 998244353;
     
    int n, m, k;
    int fac[N], S[N][N], C[N];
     
    ll qpow(ll a, ll b) {
        ll ans = 1;
        while(b) {
            if(b & 1) ans = ans * a % MOD;
            a = a * a % MOD;
            b >>= 1;   
        }
        return ans;   
    }
     
    void run(){
        S[0][0] = 1;
        for(int i = 1; i <= k; i++) {
            for(int j = 1; j <= i; j++) {
                S[i][j] = (1ll * S[i - 1][j] * j % MOD + S[i - 1][j - 1]) % MOD;
            }
        }
        C[0] = 1;
        for(int i = 1; i < N; i++) C[i] = 1ll * C[i - 1] * (n - i + 1) % MOD;
        int invm = qpow(m, MOD - 2);
        int ans = 0;
        for(int i = 0; i <= k; i++) {
            ans = (ans + 1ll * C[i] * S[k][i] % MOD * qpow(invm, i) % MOD) % MOD;
        }
        cout << ans << '
    ';
    }
     
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
        while(cin >> n >> m >> k) run();
        return 0;
    }
    
  • 相关阅读:
    找回Android studio的帮助文档
    adb shell 命令详解
    Android 获取Activity当前view
    下载网络文件HttpURLConnection.getContentLength()大小为 0
    Android设置屏幕旋转后保存数据
    解决TextView drawableRight左侧图片大小不可控的问题
    Android全屏(包含3种隐藏顶部状态栏及标题栏和一种隐藏Android 4.0平板底部状态栏的方法)
    人生苦短,我用Python(目录)
    爬虫学习目录
    Django-jet自定义菜单
  • 原文地址:https://www.cnblogs.com/heyuhhh/p/12080275.html
Copyright © 2011-2022 走看看