查找超过100,000,000的数字的第一个原始根

时间:2017-01-02 20:25:25

标签: java

这是我的代码:

  import java.io.*;
import java.util.*;
import java.text.*;
import java.math.*;
import java.util.regex.*;
import java.security.SecureRandom;

public class Solution {
    static BigDecimal result;
    static Double y = 0.0;
    static int o;
    static int[] factors = new int[1];
    static int current = 0;
    public static void main(String[] args) {
        Scanner a1 = new Scanner(System.in);
        int b = a1.nextInt();
        o = b;
        result = new BigDecimal(Integer.valueOf(b));
        BigInteger N = new BigInteger(Integer.toString(b - 1));
        factor(N);
        boolean isPrimitive = true;

        for (int i1 = 2; i1 < 10000;i1++) {
        isPrimitive = true;
        //System.out.println("Enter the value of a large prime no");
        BigInteger value = new BigInteger(String.valueOf(o-1));
        //System.out.println("\nEnter the value of alpha");
        BigInteger checking = new BigInteger(String.valueOf(i1));
        BigInteger bigValue = new BigInteger(String.valueOf(o));

        for(int i=0;i<factors.length;i++)
        {
            BigInteger temp = checking.pow(factors[i]);
           // System.out.println("checking "+i1+": "+temp+" mod "+o+" = " + (temp.mod(new BigInteger(String.valueOf(o)))));
         if ((temp.mod(bigValue)).equals(BigInteger.ONE)) {
             isPrimitive = false;
             break;
         }
        }
        if(isPrimitive) {
            System.out.print(i1+" ");
            break;
        }
        else{
            //System.out.println("not primitive roots");
        }

        }
        System.out.println(result.toBigInteger());


    }



    private final static BigInteger ZERO = new BigInteger("0");
    private final static BigInteger ONE = new BigInteger("1");
    private final static BigInteger TWO = new BigInteger("2");
    private final static SecureRandom random = new SecureRandom();

    public static BigInteger rho(BigInteger N) {
        BigInteger divisor;
        BigInteger c = new BigInteger(N.bitLength(), random);
        BigInteger x = new BigInteger(N.bitLength(), random);
        BigInteger xx = x;

        // check divisibility by 2
        if (N.mod(TWO).compareTo(ZERO) == 0) return TWO;

        do {
            x = x.multiply(x).mod(N).add(c).mod(N);
            xx = xx.multiply(xx).mod(N).add(c).mod(N);
            xx = xx.multiply(xx).mod(N).add(c).mod(N);
            divisor = x.subtract(xx).gcd(N);
        } while ((divisor.compareTo(ONE)) == 0);

        return divisor;
    }

    public static void factor(BigInteger N) {

        //System.out.println("result = "+result);
        if (N.compareTo(ONE) == 0) return;
        if (N.isProbablePrime(20)) {
           // System.out.println("n = "+N);
            if ((N.doubleValue() != (y)) &&N.doubleValue() != (1.0) ) {
                // System.out.println("j = "+String.valueOf(1.0 - (1.0/(N.doubleValue()))));
                BigDecimal j = new BigDecimal(String.valueOf(1.0 - (1.0/(N.doubleValue()))));
                //System.out.println("result = " +result+" * "+j);
                result = new BigDecimal(String.valueOf(result.doubleValue() * j.doubleValue()));
                //System.out.println(result.multiply(j));

                //System.out.println((String.valueOf(1.0 - (1.0/(N.doubleValue())))));

                y = N.doubleValue();
                if (current == factors.length) {
                    int[] temp = new int[factors.length+1]; 
                    for (int i = 0; i < factors.length;i++) {
                        temp[i] = factors[i];
                    }
                    factors = temp;

                }
                factors[current] = o/y.intValue();
               // System.out.println(o+"/"+y.intValue());
                current++;


                //System.out.println("result = "+result);
            }

            return;
        }
        BigInteger divisor = rho(N);
        factor(divisor);
        factor(N.divide(divisor));
    }



}

我试图找到素数的第一个原始根,然后是原始根的数量。找到金额对于任何数字来说都没有问题,但找到第一个数字应该适用于某个系统上任何数量高达10亿的数字,其他人已经成功。它适用于高达一百万左右的所有值,但它不适用于999994267.我不知道如何进一步优化它。我花了大概18个小时。老实说,我无法解决这个问题。有什么建议吗?

数学说明: 它需要给定数字o的因子,并测试每个数字2,如果它因此/因子[1,2,...] = 1,如果没有任何因素,它会打破并打印数字。

PS。有可能,正如许多其他人在同一系统上所做的那样。

1 个答案:

答案 0 :(得分:0)

好的,感谢上面的@IgorNikolaev在我的问题的评论中,我已经找到了问题并解决了它。要完全优化modPow操作,您需要使用模运算。

以下是他提供的一些非常有帮助的链接:

en.wikipedia.org/wiki/Modular_arithmetic

en.wikipedia.org/wiki/Modular_exponentiation

以下是我根据这些链接编写的代码:

private static BigInteger fastModPow(BigInteger base, BigInteger exponent, final BigInteger modulo) {

    BigInteger result = BigInteger.ONE;
    while (exponent.compareTo(BigInteger.ZERO) > 0) {
        if (exponent.testBit(0)) 
            result = (result.multiply(base)).mod(modulo);
        exponent = exponent.shiftRight(1);
        base = (base.multiply(base)).mod(modulo);
    }
    return result.mod(modulo);
}

正如您将在第一个链接中看到的那样,它会绕过&#34;包装&#34;找到权力的模式。

感谢大家的帮助。