使用模乘法逆查找字符串的等级(带有重复项)

时间:2015-09-23 11:38:21

标签: java algorithm rank

这里的代码适用于长度等于或小于12的字符串,如果是int,则为20。在这段代码中我使用公式(N-1)! /(p1!* p2!* p3!...)用于计算等级,其中p1,p2,p3是重复字符的出现次数。但是在大输入的情况下,因子计算的结果不适合整数(或长)。所以,我不明白我需要修复哪些代码以及如何修复?我是否需要修复因子法或者我是否需要更改公式来计算排名?据我所知,根据模乘法逆我可以使用公式(A * power(B,Mod-2))%Mod,其中A是iterativeFactorial(sorts.size()),B是countRepetitions(排序),Mod是1000003.但如果我把这个公式代替(N-1)! /(p1!* p2!* p3!...)我的结果不正确。 因此,我将非常感谢澄清使用模乘法逆计算秩和我可以修复大输入代码的方法。

示例:排名" adfadfcvcvbgfgrewfdfdsfgfgfhfhcxxse"必须是874647,但现在我有511521

public static int myFindRank(String A){
        int rank = 0;
        String sortedAndUnique = "";
        int temp;
        Set<Character> uniques = new TreeSet<Character>();
        List<Character> sorts = new ArrayList<Character>();

        for (int i = 0; i<=A.length()-1; i++){
            char x = A.charAt(i);
            uniques.add(x);
        }

        for (int i = 0; i<=A.length()-1; i++){
            char x = A.charAt(i);
            sorts.add(x);
        }

        for (Character c : uniques) {
            sortedAndUnique = sortedAndUnique + c;
        }

        for (int i = 0; i<A.length()-1; i++){
            for (int j = 0; j<A.length(); j++){

                if (A.charAt(i) == sortedAndUnique.charAt(j)) {
                    Character c = A.charAt(i);
                    sorts.remove(c);
                    i++;
                    temp = 0;

                    while (sortedAndUnique.charAt(temp) != A.charAt(i)) {
                        Character x = sortedAndUnique.charAt(temp);
                        temp++;
                        if (sorts.contains(x)) {
                            sorts.remove(x);
                            rank = rank + iterativeFactorial(sorts.size())/ countRepetitions(sorts);
                            sorts.add(x);
                        }
                    }

                    if (sortedAndUnique.charAt(temp) == A.charAt(i)) {
                        Character y = A.charAt(i);
                        sorts.remove(y);
                    }
                    break;
                } else {
                    Character c = sortedAndUnique.charAt(j);
                    if (sorts.contains(c))  {
                        sorts.remove(c);
                        rank = rank + iterativeFactorial(sorts.size())/ countRepetitions(sorts);
                        sorts.add(c);
                    }
                }
            }
        }

        return (rank+1)%1000003;
    }


public static int countRepetitions(List A){

        int repetitions = 1;

        List<Character> chars = new ArrayList<Character>();
        Set<Character> unique = new TreeSet<Character>();

        for (int i = 0; i<=A.size()-1; i++){
            Character x = (Character) A.get(i);
            chars.add(x);
            unique.add(x);

        }

        for (Character c : unique) {
            repetitions = repetitions * iterativeFactorial(Collections.frequency(chars, c));

        }
        return repetitions;

    }


public static int iterativeFactorial(int number) {

        if (number == 0)
            return 1;

        int i;
        for(i=number; number>1; i=i*number) {
            number--;

        }
        return i;
    }

自定义电源方法:

 public static int callPow(int num)

    {

        int ans = 1, base = num;

        int power = 1000003 - 2;

        while (power > 0) {

            if (power == 1) {

                return (ans * base) % 1000003;

            }

            if (power % 2 == 0) {

                base = (base * base) % 1000003;

                power /= 2;

            } else {

                ans = (ans * base) % 1000003;

                power--;

            }

        }

        return ans;

    }

1 个答案:

答案 0 :(得分:2)

  

据我所知,根据模乘法逆我可以使用公式(A * power(B,Mod-2))%Mod,

虽然在数学上是正确的,但这可能会溢出。您需要在每个步骤使用模数:

[(A % Mod) * (power(B, Mod - 2) % Mod)] % Mod

所以在你的代码中:

    for(i=number; number>1; i=i*number) {

更改为:

    for(i=number; number>1; i=(i*number) % Mod) {
repetitions = repetitions * iterativeFactorial(Collections.frequency(chars, c));

更改为:

repetitions = (repetitions * iterativeFactorial(Collections.frequency(chars, c))) % Mod;

注意:您应该使用Mod*Mod适合的数据类型!

而且我不确定你在第一种方法中做了什么。您不应该有涉及模运算的任何分区。使用你提到的功率公式。