2020牛客暑期多校第五场E题-Bogo Sort (置换、大数)

题目链接:2020牛客暑期多校第五场E题-Bogo Sort

题意

给出一个置换 \(p\),问 \(1\sim n\)\(n\) 个数有多少种排列,能经过若干次 \(p\) 的置换后变成有序?答案对 \(10^n\) 取模。


思路

题意也等价于有序的 \(1\sim n\) 经过 \(p\) 的若干次置换,能形成多少种不同的排列。

记置换 \(P\)\(z\) 个环,长度分别为 \(C_1,C_2,...,C_z\)\(1\sim n\) 分别经过 \(x_1\)\(x_2\) 次置换后,记 \(S_1=\{x_1\%C1,x_1\%C_2,...,x_1\%C_z\},S_2=\{x_2\%C1,x_2\%C_2,...,x_2\%C_z\}\) ,当且仅当 \(S_1\ne S_2\) ,形成的排列不同。

\(L=lcm(C_1,C_2,...,C_z)\) ,当 \(|x_1-x_2|\ne y\cdot L, y\in N^*\) ,有 \(S_1\ne S_2\) 。显然最多有 \(L\) 个不同的 \(x\) ,满足 \(|x_i-x_j|\ne y\cdot L, i\in[1,L],j\in [1,L],i\ne j\) ,即最多形成 \(L\) 种不同的排列,所以答案为 \(L\)

对于取模,实际上 \(L\) 肯定小于 \(10^n\) ,所以不用取模。令 \(L'=\prod_{i=1}^z C_i\) ,显然 \(L'\ge L\) ;由于 \(\sum_{i=1}^z C_i=n\) ,可按如下方法构造出最大的 \(L'\)

\[\begin{cases}\forall i\in[1,z], C_i=2, &if\ n\ is\ even \\ \forall i\in[1,z-1],C_i=2,Cz=3 &if\ n\ is\ odd\end{cases} \\ \Downarrow \\L'=\begin{cases}2^{n/2}, &if\ n\ is\ even \\2^{(n-3)/2}\cdot 3 &if\ n\ is\ odd\end{cases} \]

显然 \(L\le L' \lt 10^n\)


代码实现

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Scanner;
 
public class Main{
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int p[] = new int[n+10];
        boolean vis[] = new boolean[n+10];
        for (int i = 1; i <= n; i++) p[i] = sc.nextInt();
        ArrayList<Integer> C = new ArrayList<Integer>();
        for (int i = 1; i <= n; i++) {
            int ci = 0, tmp = i;
            while (!vis[tmp]) {
                vis[tmp] = true;
                ci++;
                tmp = p[tmp];
            }
            if (ci > 0) C.add(ci);
        }
        BigInteger ans = BigInteger.ONE;
        for (int ci : C) {
            BigInteger g = ans.gcd(BigInteger.valueOf(ci));
            ans = ans.multiply(BigInteger.valueOf(ci)).divide(g);
        }
        System.out.println(ans);
    }
}
posted @ 2020-07-27 21:52  _kangkang  阅读(222)  评论(0编辑  收藏  举报