从diff构造装饰的方法。彩色珠子(图论算法)

时间:2013-06-04 06:01:13

标签: algorithm graph tree graph-theory

有N种颜色的珠子。你有第i种颜色的双珠。你想通过将所有珠子连​​接在一起来制作装饰品。您可以使用以下算法创建装饰:

步骤#1以任何顺序排列所有珠子,使相同颜色的珠子放在一起。

步骤#2装饰物最初仅由排列中的第一个珠子组成。

步骤#3按顺序对每个后续珠子,将其连接到装饰物中相同颜色的珠子。如果没有相同颜色的珠子,它可以连接到装饰品中的任何珠子。

即使它们具有相同的颜色,所有珠子都是不同的。按照上述算法可以形成多少个不同的饰物?如果两个珠子在一种配置中通过螺纹连接而在另一种配置中没有连接,则认为两个饰品是不同的。

澄清

将珠子形成为树而不是直线。任何数量的珠子都可以连接到珠子上。

这个问题让我抓狂!我被告知你必须使用Cayleys算法来获得为每个颜色ci珠子构建树的所有方法,然后你必须将树木连接在一起。据说有这个公式用于将组件连接到树中,(s1s2 ... sk)×nk - 2,但我不确定我是否正确配方,我也不相信。有人熟悉这个公式,或者可以帮助我解决这个问题。多谢你们。哦顺便说一下,这是我到目前为止的算法。它正在研究一些测试用例,但也失败了。

公共课BeadOrnament {

public static void main(String[] args) {

    Scanner stdin = new Scanner(System.in);

    int T, N;

    T = stdin.nextInt();

    while (T-- > 0) {

        N = stdin.nextInt();

        double[] colors = new double[N];
        double[] trees = new double[N];

        long ornaments = 0;

        for (int i = 0; i < N; i++) {
            colors[i] = stdin.nextInt();
        }

        long t = 1;
        for (int i = 0; i < N; i++) {
            trees[i] = Math.max(Math.pow(colors[i], colors[i] - 2), 1);
            t *= trees[i];
        }

        long s = 1;

        if (N > 1) {

            for (int i = 0; i < N; i++) {
                s *= colors[i];
            }

            s *= Math.max(Math.pow(N, colors.length - 2), 1);

        }

        ornaments = s * t;

        System.out.println(ornaments);
    }
}

}

2 个答案:

答案 0 :(得分:2)

使用指数函数和大量乘法时要注意的一件事是溢出。如果你超过2 52 ,双打就会失去精确度。已经超过16个珠子超过此限制。

考虑使用Java的BigInteger代替。 Cayleys公式然后变成:

BigInteger numberOfOrnaments(int beadCount) {
    if (beadCount <= 2) {
        return BigInteger.ONE;
    }
    return BigInteger.valueOf(beadCount).pow(beadCount-2);
}

我找不到任何将饰品(跨越树木)加在一起的公式。您的代码至少应该对N <= 2正确,因为您只添加一个字符串。对于N > 2我不能说它是否会起作用。

我的直觉是,你可以通过连接任意两个珠子(每棵树一个)来连接两棵树。对于珠子计数n1n2,可以n1*n2方式进行。第三棵树你可以连接到另外两棵树中的任何一棵树,但你也可以将它们连接到第三棵树,而不先加入它们。公式很快变得非常复杂。


阿。现在我明白了。我想到的复杂公式,用于加入饰品,简化为n1*n2*n3*...*nk*(n1+n2+n3+...+nk)^(k-2),其中每个ni是颜色i的珠数。

BigInteger totalNumberOfConfigurations(int[] beadCounts) {
    BigInteger result = BigInteger.ONE;
    int sum = 0;
    for (int n : beadCounts) {
        result = result.multiply(numberOfOrnaments(n))
        result = result.multiply(BigInteger.valueOf(n));
        sum += n;
    }
    BigInteger x = BigInteger.valueOf(sum).pow(beadCounts.length - 2);
    result = result.multiply(x);
    return result;
}

答案 1 :(得分:0)

这是最终答案。非常感谢Markus Jarderot。就在你的帖子之前我尝试了你给出的正确公式,但我的实现有一个错误,错误的变量用法(愚蠢的错误)。再次感谢。

import java.math.BigInteger;
import java.util.Scanner;

public class BeadOrnament {

    public static void main(String[] args) {
        // TODO code application logic here
        Scanner stdin = new Scanner(System.in);

        int T, N;

        T = stdin.nextInt();

        while (T-- > 0) {

            N = stdin.nextInt();

            int[] colors = new int[N];
            BigInteger[] trees = new BigInteger[N];

            BigInteger ornaments;

            for (int i = 0; i < N; i++) {
                colors[i] = stdin.nextInt();
            }

            BigInteger t = BigInteger.valueOf(1);
            for (int i = 0; i < N; i++) {
                trees[i] = numberOfTrees(colors[i]);
                t = t.multiply(trees[i]);
            }

            BigInteger sp = BigInteger.valueOf(1);
            BigInteger ss = BigInteger.valueOf(0);
            BigInteger tot = BigInteger.valueOf(0);

            for (int i = 0; i < N; i++) {
                sp = sp.multiply(BigInteger.valueOf(colors[i]));
                ss = ss.add(BigInteger.valueOf(colors[i]));
            }

            if (N > 2) {
                ss = ss.pow(colors.length - 2);
                ss = ss.multiply(sp);
                tot = ss;
                ornaments = tot.multiply(t);
            } else if (N == 2) {
                tot = sp;
                ornaments = tot.multiply(t);
            } else {
                ornaments = t;
            }

            System.out.println(ornaments.mod(BigInteger.valueOf(1000000007)));
        }
    }

    public static BigInteger numberOfTrees(int beadCount) {
        if (beadCount <= 2) {
            return BigInteger.ONE;
        }
        return BigInteger.valueOf(beadCount).pow(beadCount - 2);
    }
}