Polya定理

题源:

Luogu4980.

题意:

\(n\) 点环,每个点可以写 \(1 \ldots n\) 中的一个数,问有多少旋转后本质不同的染色方案。

\(\rm Analysis:\)

\(\operatorname{burnside}\) 引理,仍然是考虑每个置换操作的等价类个数,发现对于一个往后 \(k\) 的置换,一共会构成 \(\gcd(n, k)\) 个环,环内部是同色,所以所求就是:

\[\begin{aligned} \sum _ {i = 1} ^ n n ^ {(n, i)} &= \sum _ {d \mid n} n ^ d \sum _ {i = 1} ^ n [(i, n) = d] \\ &= \sum _ {d \mid n} n ^ d \sum _ {i = 1} ^ {\lfloor \frac{n}{d} \rfloor} [(i, \frac{n}{d}) = 1] \\ &= \sum _ {d \mid n} n ^ d \varphi(\frac{n}{d}) \end{aligned} \]

枚举约数即可,暴力按照定义求 \(phi\)

一定要记得 polya 定理最后要取平均值!

\(\rm Code:\)

using i64 = long long;
const int md = 1e9 + 7;

signed main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int T;
    std::cin >> T;
    while (T--) {
        int n;
        std::cin >> n;
        i64 res = 0;
        for (int i = 1; i * i <= n; ++i) {
            if (n % i == 0) {
                res = (res + pwer(n, i) * phi(n / i) % md) % md;
                if (i * i != n) 
                    res = (res + pwer(n, n / i) * phi(i) % md) % md;
            }
        }

        std::cout << res * pwer(n, md - 2) % md << '\n';
    }
}
posted @ 2021-08-10 17:18  Z_char  阅读(100)  评论(0编辑  收藏  举报