zoukankan      html  css  js  c++  java
  • Codeforces Round #614 (Div. 1)

    Codeforces Round #614 (Div. 1)

    AB

    C

    先观察规律确定dp方程式,然后记搜优化(略)

    D

    建出整棵树空间不太够( (3 imes10^7) 个节点 ),只能考虑类似虚树的思想。其实只需要知道每个子树里有多少节点,然后不断移动来确定重心(略)

    E

    如果能确定两种字母,剩下的都是第三种。那么询问 (CO,CH,CC,HO,OO),花费 (1.25),此时已经得到了除了最后一个位置的所有 (C) 和除了第一个位置的所有 (O),也就是说,([2,n-1]) 的所有字符已经确定。如果 (p_1) 还未确定,(p_1) 只能是 (O,H),假设答案为某一个,询问一次 ([1,n-1]) 即可得出 (p_1),用同样的方法询问一次 ([1,n]) 可以得出 (p_n),总花费 (1.25+frac{1}{(n-1)^2}+frac{1}{n^2})

    (n=4) 时需要特殊处理:先依次问 (CO,CH,CC,HO),如果某一个存在,就用类似上面确定 (p_1,p_n) 的方法确定剩余两位。否则询问 (OO),如果 (OO) 存在,(O) 一定占满了一段长度 (ge2) 的前缀(因为不存在 (CO,HO)),最坏的情况是只确定前面两个为 (O),那么一定有 (p_3=H),然后再问一次 ([1,n]) 确定 (p_4)。如果 (OO) 不存在,一定有 (p_2=p_3=H)(p_1=O/H,p_4=C/H),问一次 (HHH) 即可全部确定

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 52;
    int n, m, k[N], w[N], tag[N]; char res[N];
    #define flush fflush (stdout)
    #define pc putchar
    void query (string s) {
        cout << "? " << s << '
    ';
        flush; memset (tag, 0, sizeof (tag)); cin >> m;
        for (int i = 1; i <= m; ++i) cin >> w[i], tag[w[i]] = 1;
    }
    void get (string s) {
        query (s);
        for (int i = 1, x; i <= m; ++i) {
            k[x = w[i]] = k[x + 1] = 1;
            res[x] = s[0], res[x + 1] = s[1];
        }
    }
    void solvea () {
        get ("CH"), get ("CO"), get ("CC"), get ("OO"), get ("HO");
        for (int i = 2; i < n; ++i) if (!k[i]) res[i] = 'H';
        if (!k[1]) {
            string s = "H";
            for (int i = 2; i < n; ++i) s += res[i];
            query (s); res[1] = tag[1] ? 'H' : 'O';
        }
        if (!k[n]) {
            string s = "";
            for (int i = 1; i < n; ++i) s += res[i];
            query (s + 'H'); res[n] = tag[1] ? 'H' : 'C';
        }
    }
    void work () {
        int l = w[1], r = w[1] + 1; string s;
        for (int i = l - 1; i >= 1; --i) {
            s = ""; for (int j = i + 1; j <= r; ++j) s += res[j];
            query ('H' + s); if (tag[i]) { res[i] = 'H'; continue; }
            query ('O' + s); res[i] = tag[i] ? 'O' : 'C';
        }
        for (int i = r + 1; i <= n; ++i) {
            s = ""; for (int j = 1; j < i; ++j) s += res[j];
            query (s + 'H'); if (tag[1]) { res[i] = 'H'; continue; }
            query (s + 'O'); res[i] = tag[1] ? 'O' : 'C';
        }
    }
    void solveb () {
        get ("CH"); if (m) { work (); return; }
        get ("CO"); if (m) { work (); return; }
        get ("CC"); if (m) { work (); return; }
        get ("HO"); if (m) { work (); return; }
        get ("OO");
        if (m) {
            int pos = 0;
            for (int i = 1; i <= n; ++i)
                if (!k[i]) { pos = i; break; }
            if (!pos) return;
            if (pos == 3) res[3] = 'H';
            string s = "";
            for (int i = 1; i <= 3; ++i) s += res[i];
            query (s + 'H');
            res[n] = tag[1] ? 'H' : 'C';
        } else {
            query ("HHH"); res[2] = res[3] = 'H';
            res[1] = tag[1] ? 'H' : 'O';
            res[n] = tag[2] ? 'H' : 'C';
        }
    }
    signed main() {
        int T, qwq; cin >> T;
        while (T--) {
            cin >> n; memset (k, 0, sizeof (k));
            n > 4 ? solvea () : solveb ();
            pc ('!'), pc (' ');
            for (int i = 1; i <= n; ++i) pc (res[i]);
            puts (""); flush; cin >> qwq;
        }
    }
    

    F

    (a_x|a_y),连边 ((x,y)),形成一张 (DAG),对每个连通块单独处理。用计算加点方案代替删点方案。若存在 ((x,y),(y,z)),必存在 ((x,z)),所以一个点能不能加入只需记录“已激活”的无入边的点的集合(最大 (15)),然后 (dp) 一下,设 (f_{i,j}) 为激活点集为 (i),已经加入了 (j) 个点,转移分两种:一种是不改变 (i),选择的方案数与 (i) 可达点数有关;另一种是改变 (i),直接枚举加入点。

  • 相关阅读:
    总结类初始化时的代码执行顺序
    Calcite数据源适配器对时间字段的操作问题
    如何自定义一个Calcite对Tablesaw查询的适配器
    Redis集群 Redis Cluster
    培养代码逻辑
    在线查看office文件的两种方法
    WPF Prism框架合集(9.Dialog)
    WPF Prism框架合集(8.Navigation)
    WPF Prism框架合集(7.Mvvm)
    springboot @OneToOne 解决JPA双向死循环/返回json数据死循环
  • 原文地址:https://www.cnblogs.com/whx666/p/614-div1.html
Copyright © 2011-2022 走看看