某岛

… : "…アッカリ~ン . .. . " .. .
October 14, 2014

2014 ACM/ICPC Asia Mudanjiang Regional Contest Onsite

Problem B. Domination

Brief description:

给定一棵无根树 T 。定义以 T 上一对点 (a, b) 为“复根”的树的高度 h(a, b) = max min(dist(x, a), dist(x, b)), for all x on T 。
现求 H(T) = min h(a, b), for all (a, b) | a != b。

Analysis:

结论:两个复根一定在树的直径上。

先求直径,并求出直径上每个点为根的树所到达的最远距离。
二分答案,每次先贪心的将复根尽可能向中间移动。。。然后在判断中间的那些点是否也合法。

http://acm.hust.edu.cn/vjudge/problem/viewSource.action?id=2882177

Problem D. Domination

Brief description:

略。)

Analysis:

似乎是某场 CF 的 B。

f[i][j][k]: 表示当前有 i 行、j 列没有覆盖,且一共还有 k 个格子没填时的期望。
转移分四种情况讨论即可。(似乎这个状态表示不是特别好。。这样做必须要使用 long double。。)

//}/* .................................................................................................................................. */

const int N = 51;
long double f[N][N][N*N];
int n, m;

int main(){

#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
#endif

    Rush{
        RD(n, m); RST(f);

#define u f[i][j][k]
        REP_2(i, j, n+1, m+1){
            if (!i && !j) continue;
            REP_1(k, n*m){
                u = (k-i*m-j*n+i*j) * f[i][j][k-1];
                if (i && j) u += i*j * f[i-1][j-1][k-1];
                if (i) u += i*(m-j) * f[i-1][j][k-1];
                if (j) u += j*(n-i) * f[i][j-1][k-1];
                u /= k, ++u;
            }
        }

        OT((DB)f[n][m][n*m]);
    }
}

Problem F. Fiber-optic Network

Brief description:

给定一颗 50 个结点的无向树,每个结点可以填 [Li, Ri] 之间的数。
要求相邻结点填的数 co-prime。问一共有多少种方案。(要求输出所有方案里每个结点所填的数字和)

Analysis:

树 DP,容斥原理转移。

f1[u][val]:表示 u 点填 val 时的方案数。。。
用容斥原理进行转移。。。

考虑 (u, v) 的转移,设 f2[v][val] 为 v 结点所有以 val 为倍数的答案。我们预处理出 mu 函数,以及 val 所有的 mu 值不为 0 的倍数。。
那么就是:

    ECH(it, adj[u]) if (v != p){
        FOR_1(i, ll[u], rr[u]){
            Int t = 0; ECH(d, dd[i]) t += Int(mu[*d])*f2[v][*d];            
            f1[u][i] *= t;
        }
    }

dfs 两次。。
第一次可以得到根结点的答案。。
为了得到其它结点的答案。。需要将父亲结点的结果除去以某个 v 作为孩子时的方案数作为一个新的孩子。。。参与转移。。
得用一些麻烦的方法避免除法。。。TLE…

http://acm.hust.edu.cn/vjudge/problem/viewSource.action?id=2844775

改进:
按照边进行 DP。。。
f1[i][val]:i 表示 (p, u) 这条边。。。
。。u 点填 val 时的方案数。。。可以避免除法。。

http://acm.hust.edu.cn/vjudge/problem/viewSource.action?id=2845448

Problem K.

Brief description:

Analysis:

贪心。。digit 总是越靠前越好。。
。先在前面补齐必要的 digit。。。然后贪心的将最前的非法 * 和最后的 digit 交换。

//}/* .................................................................................................................................. */

string s;
int n;

int main(){

#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
#endif

    Rush{
        cin >> s; n = s.size();
        int a = 0; REP(i, n) if (s[i] == '*') ++a;
        int b = n - a, bb = 0, z = 0; z += max(0, a-(b-1)); bb = z;
        REP(i, n) if (s[i] == '*'){
            if (bb < 2) ++bb, ++z;
            else --bb;
        }
        else ++bb;
        cout << z << endl;
    }
}

http://acm.hust.edu.cn/vjudge/problem/viewSource.action?id=2845839