Educational Codeforces Round 84 (CDE)

C. Game with Chips

题目: https://codeforces.com/contest/1327/problem/C

题解

先将\(k\)\(chip\)移到同一个点:左上角。然后,走\(S\)形遍历整个图就行了
最多操作次数: \((n - 1) + (m - 1) + (n * m - 1)\) \(<\) \(2 * n * m\)
(秒啊,没想到将它们移到同一点)

D. Infinite Path

题目:https://codeforces.com/contest/1327/problem/D

题解

官方题解的描述实在蛋疼
推荐这位博主:https://blog.csdn.net/weixin_44178736/article/details/105180870?>

首先,一般都能观察到满足定义的\(Infinite\) \(Path\)构成了一个环,既存在\(p[p[···p[i]]] = i\)。实际上,一个排列 \(p\) 按照\((i, p[i])\)建边后形成的图恰好是由这样的环(\(Infinite\) \(Path\))组成。模拟一下\(p^k\)的操作,发现\(p^k\)可以看做是每个点在环上不停的移动\(k\)次(动笔画一下比较好理解)。
然后,枚举\(k\)。记环的长度为\(m\),假设 \(m\) \(\%\) \(k\) \(!= 0\),那么对于任意一点,不停的移动,最终都会经过所有的点,等价于\(k = 1\),所以只需要枚举\(m\)的因数,将其作为\(k\)就行。实际上,有点类似离散数学中的:等价类。将原来的1个环划分为现在的\(k\)个环。
最后,检查这\(k\)个环中所有的点的颜色是否相同就行,满足的话更新答案。

复杂度的证明请看讨论:https://codeforces.com/blog/entry/75147


void Solve() {
    int n;
    scanf("%d", &n);

    vector<int> p(n + 1), color(n + 1), use(n + 1, 0);
    myfor(i, 0, n) scanf("%d", &p[i + 1]);
    myfor(i, 0, n) scanf("%d", &color[i + 1]);

    int ans = INF;
    myfor(i, 0, n) if (!use[p[i + 1]]) {
        int v = p[i + 1];

        vector<int> cycle;
        while(!use[v]) {
            use[v] = 1;
            cycle.push_back(v);
            v = p[v];
        }
        
        myfor(step, 1, cycle.size() + 1) if (cycle.size() % step == 0) {    // 枚举 k
            myfor(j, 0, step) {        // 枚举起点
                bool flag2 = true;

                //检查环中的每个点颜色是否相同
                for (int k = j; k  + step < cycle.size(); k += step) if (color[cycle[k]] != color[cycle[k + step]]) {      
                    flag2 = false;
                    break;
                }

                if (flag2) {
                    ans = min(ans, step);
                    break;
                }
            }

        }
    }
    
    cout << ans << endl;
    return;
}

E. Count The Blocks

题目:https://codeforces.com/contest/1327/problem/E

题解

①长度为\(len\)的块在中间

  • \(ans_{len} = (n - len - 1) * 10 * 9 * 9 * 10^{n - len - 2}\)

②长度为\(len\)的块在两端

  • \(ans_{len} = 2 * 10 * 9 * 10 ^{n - len - 1}\)

纯粹就是组合数学问题,类似于有m个座位,n个人坐在一起且相邻,既任意两个人之间没有空位,问有多少种方案。本题只是多了些限制条件

int n;
long long d[MAXN];

void Inite() {
    d[0] = 1;
    for (int i = 1; i < MAXN; ++i) d[i] = d[i - 1] * 10 % mod;
}

int main() {

    cin >> n;

    Inite();

    for (int i = 1; i <= n; ++i) {
        long long ans = 0;
        if (n - i >= 2) ans = ((n - i - 1) * 81 * d[n - i - 1] % mod + ans) % mod;
        if (n - i >= 1) ans = (18 * d[n - i] + ans) % mod;
        else ans = (10 + ans) % mod;
        cout << ans << " ";
    }

    cout << endl;
    return 0;
}

posted @ 2020-04-01 13:52  天之道,利而不害  阅读(192)  评论(0编辑  收藏  举报