zoukankan      html  css  js  c++  java
  • The Preliminary Contest for ICPC Asia Xuzhou 2019

    A What is better?

    推不出来,写个程序打表,用扩展中国剩余定理合并,居然会溢出longlong,还好不会溢出__int128(赛后exit(-1)测试),实际证明溢出返回-1是不靠谱的,毕竟后面可以又把它搞小了。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef __int128 lll;
    
    const int MAXK = 10 + 5;
    
    void exgcd(lll a, lll b, lll &x, lll &y) {
        if(!b)
            x = 1, y = 0;
        else
            exgcd(b, a % b, y, x), y -= a / b * x;
    }
    
    lll inv(ll a, ll b) {
        lll x = 0, y = 0;
        exgcd(a, b, x, y);
        x = (x % b + b) % b;
        if(!x)
            x += b;
        return x;
    }
    
    int k;
    lll c[MAXK], m[MAXK];
    
    lll exCRT(int k) {
        lll c1, c2, m1, m2, t;
        for(int i = 2; i <= k; ++i) {
            m1 = m[i - 1], m2 = m[i], c1 = c[i - 1], c2 = c[i];
            t = __gcd(m1, m2);
            if((c2 - c1) % t != 0)
                return -1;
            m[i] = m1 / t * m2;
            if(m[i] <= 0)
                exit(-1);
            c[i] = inv(m1 / t, m2 / t) * ((c2 - c1) / t) % (m2 / t) * m1 + c1;
            c[i] = (c[i] % m[i] + m[i]) % m[i];
        }
        return c[k];
    }
    
    /*map<pair<int, int>, pair<bool, int> > M;
    
    bool dfs(int id, int pre) {
        if(M.count({id, pre}))
            return M[ {id, pre}].first;
        if(pre == -1) {
            for(int i = 1; i < id; ++i) {
                if(dfs(id - i, i) == false) {
                    M[{id, pre}] = {true, i};
                    return true;
                }
            }
            M[{id, pre}] = {false, -1};
            return false;
        } else {
            int c = min(2 * pre, id);
            if(c == id) {
                M[{id, pre}] = {true, c};
                return true;
            }
    
            for(int i = 1; i <= c; ++i) {
                if(dfs(id - i, i) == false) {
                    M[{id, pre}] = {true, i};);
                    return true;
                }
            }
            M[{id, pre}] = {false, -1};
            return false;
        }
    }*/
    
    ll f[72 + 5];
    
    int main() {
    #ifdef local
        freopen("lyz.in", "r", stdin);
    #endif // local
        /*for(int i = 2; i <= 100; ++i) {
            printf("i=%d", i);
            if(dfs(i, -1)) {
                printf(" WIN
    ");
                printf(" TO TAKE %d
    ", M[ {i, -1}].second);
            } else
                printf(" FAIL
    ");
        }
    
        for(int j = 1; j <= 20; ++j) {
            for(int k = -1; k <= 20; ++k) {
                if(M.count({j, k})) {
                    printf("(%d,%d) 
    ", j, k);
                    if(M[ {j, k}].first == true) {
                        printf(" WIN
    ");
                        printf(" TO TAKE %d
    ", M[ {j, k}].second);
                    } else {
                        printf(" FAIL
    ");
                    }
                    puts("");
                }
            }
        }*/
    
        int k;
        scanf("%d", &k);
        bool suc = 1;
        for(int i = 1; i <= k; ++i) {
            ll tmp1, tmp2;
            scanf("%lld%lld", &tmp1, &tmp2);
            m[i] = tmp1;
            c[i] = tmp2;
            if(c[i] > 1e15) {
                suc = false;
            }
        }
    
        if(!suc) {
            puts("Tankernb!");
            return 0;
        }
    
        lll n = exCRT(k);
        if(n <= 1 || n > 1e15) {
            puts("Tankernb!");
            return 0;
        }
        f[1] = 2;
        f[2] = 3;
        for(int i = 3; i <= 72; ++i) {
            f[i] = f[i - 1] + f[i - 2];
            if(f[i] >= 1e15) {
                //cout<<"i="<<i<<endl;
                break;
            }
        }
        for(int i = 1; i <= 72; ++i) {
            if(n == f[i]) {
                puts("Lbnb!");
                return 0;
            }
        }
        puts("Zgxnb!");
        return 0;
    }
    

    B so easy

    一开始1e6弄个set莽了两次,果断T了,事实证明平衡树的常数的确相比离散化是在是太大了。用个并查集维护,删除一个节点的时候,假如他没有被删除过,那么就把他指向他的下一个元素(无论他的下一个元素是不是被删了都可以),并且把这个元素设置为“删除”,下面参照非递归路径压缩并查集弄了一个非递归路径压缩,实测727ms还算可以。

    #include<bits/stdc++.h>
    using namespace std;
    
    inline int read() {
        int x = 0;
        char ch = getchar();
        while(ch < '0' || ch > '9')
            ch = getchar();
        do {
            x = (x << 3) + (x << 1) + ch - '0';
            ch = getchar();
        } while(ch >= '0' && ch <= '9');
        return x;
    }
    
    const int MAXN = 1e6;
    int z[MAXN + 5], x[MAXN + 5];
    int px[2 * MAXN + 5], xtop;
    
    int nxt[2 * MAXN + 5];
    bool vis[2 * MAXN + 5] = {};
    
    inline int find(int i) {
        int cur = nxt[i];
        while(vis[cur]) {
            cur = nxt[cur];
        }
        while(nxt[i] != cur) {
            int t = nxt[i];
            nxt[i] = cur;
            i = t;
        }
        return cur;
    }
    
    int main() {
    #ifdef local
        freopen("lyz.in", "r", stdin);
    #endif // local
        int n = read(), q = read();
        xtop = 0;
        for(int i = 1; i <= q; ++i) {
            z[i] = read(), x[i] = read();
            px[++xtop] = x[i];
            if(z[i] == 1)
                px[++xtop] = x[i] + 1;
        }
        sort(px + 1, px + 1 + xtop);
        xtop = unique(px + 1, px + 1 + xtop) - (px + 1);
        for(int i = 1; i <= q; ++i)
            x[i] = lower_bound(px + 1, px + 1 + xtop, x[i]) - (px);
    
        for(int i = 1; i <= xtop; ++i)
            nxt[i] = i;
    
        for(int i = 1; i <= q; ++i) {
            if(z[i] == 1) {
                if(!vis[x[i]]) {
                    vis[x[i]] = true;
                    nxt[x[i]] = nxt[x[i] + 1];
                    find(x[i]);
                }
            } else {
                int res = find(x[i]);
                printf("%d
    ", px[res]);
            }
        }
    
    }
    

    J Random Access Iterator

    一个逗逼签到题,根据期望的线性性蛮好推的,首先第一遍dfs算出最大深度和各个节点的深度(虽然各个节点的深度是不必要的),第二遍dfs把dp数组算出来。设dp[i]表示i的子树给出最大深度的概率。那么对于深度为最大深度的叶子节点,dp[i]=1,其他叶子dp[i]=0。那么对于中间节点,它的所有k个子节点能提供最大深度的概率的期望就是各个子节点的dp值的平均值。它不能给出正确深度的概率就是这个期望的补数连续乘k次。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int MOD = 1e9 + 7;
    
    const int MAXN = 1e6;
    vector<int> G[MAXN + 5];
    
    int qpow(ll x, int n) {
        ll res = 1;
        while(n) {
            if(n & 1)
                res = res * x % MOD;
            x = x * x % MOD;
            n >>= 1;
        }
        return res;
    }
    
    int dp[MAXN + 5];
    
    int MAXD;
    
    void dfs1(int u, int p, int d) {
        MAXD = max(MAXD, d);
        for(auto v : G[u]) {
            if(v != p) {
                dfs1(v, u, d + 1);
            }
        }
        return;
    }
    
    void dfs2(int u, int p, int d) {
        if(d == MAXD) {
            dp[u] = 1;
            return;
        }
        ll P = 0;
        int n = 0;
        for(auto v : G[u]) {
            if(v != p) {
                dfs2(v, u, d + 1);
                P += dp[v];
                ++n;
            }
        }
        P = P * qpow(n, MOD - 2) % MOD;
        ll Q = (1ll - P + MOD) % MOD;
        Q = qpow(Q, n);
        dp[u] = (1ll - Q + MOD) % MOD;
        return;
    }
    
    int main() {
    #ifdef local
        freopen("lyz.in", "r", stdin);
    #endif // local
        int n;
        scanf("%d", &n);
        for(int i = 1; i <= n - 1; ++i) {
            int u, v;
            scanf("%d%d", &u, &v);
            G[u].push_back(v);
            G[v].push_back(u);
        }
    
        dfs1(1, -1, 1);
        dfs2(1, -1, 1);
    
        printf("%d
    ", dp[1]);
    }
    

    M Longest subsequence

    设dp[i]表示匹配t串的长度为i的前缀需要用到s的最短长度,特别地为了统一,dp[0]=0,INF表示无法匹配。设pos[i][ch]表示在s串的i位置及其以后第一个ch出现的下标。

    那么只有两种情况,第一,匹配了长度为i的前缀,然后从第i+1个字符开始严格大,i从0开始,这样就暴力一遍比t[i+1]大的最近的pos就行了。第二,完全匹配t,然后后面有多少加多少,注意至少要加一个

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int INF = 1e9;
    const int MAXN = 1e6;
    char s[MAXN + 5], t[MAXN + 5];
    int dp[MAXN + 5];
    
    int pos[MAXN + 5][26];
    
    int main() {
    #ifdef local
        freopen("lyz.in", "r", stdin);
    #endif // local
        int n, m;
        while(~scanf("%d%d", &n, &m)) {
            scanf("%s%s", s + 1, t + 1);
            dp[0] = 0;
            for(int i = 1; i <= m; ++i)
                dp[i] = INF;
            for(int i = 1; i <= m; ++i) {
                for(int j = dp[i - 1] + 1; j <= n; ++j) {
                    if(s[j] == t[i]) {
                        dp[i] = j;
                        break;
                    }
                }
                if(dp[i] == INF)
                    break;
            }
    
            for(int i = 0; i < 26; ++i)
                pos[n + 1][i] = INF;
            for(int i = n; i >= 1; --i) {
                for(int j = 0; j < 26; ++j)
                    pos[i][j] = pos[i + 1][j];
                pos[i][s[i] - 'a'] = i;
            }
    
            int ans = -1;
    
            for(int i = 0; i <= m; ++i) {
                int last = INF;
                if(dp[i] == INF)
                    break;
                else {
                    if(i == m) {
                        if(dp[i] != n)
                            ans = max(ans, i + n - (dp[i] + 1) + 1);
                    } else {
                        for(int j = t[i + 1] - 'a' + 1; j < 26; ++j)
                            last = min(last, pos[dp[i] + 1][j]);
                        ans = max(ans, i + n - last + 1);
                    }
                }
            }
            printf("%d
    ", ans);
        }
    }
    
  • 相关阅读:
    28 对10个数进行排序
    27 求100之内的素数
    26 请输入星期几的第一个字母,判断一下是星期几
    25 一个五位数,判断它是不是回文数
    24 给一个不多于5位的正整数
    23 请问第5个人多大?
    22 1+2!+3!+...+5!的和
    快捷生成getter和setter方法
    Error creating bean with name 'as' defined in class path resource
    CentOS7-1810 系统DNS服务器BIND软件配置说明
  • 原文地址:https://www.cnblogs.com/Inko/p/11483758.html
Copyright © 2011-2022 走看看