如何在Java中实现AKS测试来确定一个数字是否为素数?

如何在Java中实现AKS测试来确定一个数字是否为素数?,java,algorithm,optimization,Java,Algorithm,Optimization,我首先编写了一些伪代码。我在编写expand多项式()方法时遇到问题。另外,我不知道如何在isPrime()中表示任意的int x。 以下是解释AKS的链接: 公共类解决方案{ 公共静态void main(字符串[]args) { 扫描仪扫描=新扫描仪(System.in); int n=scan.nextInt(); System.out.println(isPrime(n)); } 私有静态布尔iPrime(int p) { /* AKS素性测试表明如果 ((x-1)^p-(x^p-1))模

我首先编写了一些伪代码。我在编写expand多项式()方法时遇到问题。另外,我不知道如何在isPrime()中表示任意的int x。 以下是解释AKS的链接:

公共类解决方案{
公共静态void main(字符串[]args)
{
扫描仪扫描=新扫描仪(System.in);
int n=scan.nextInt();
System.out.println(isPrime(n));
}
私有静态布尔iPrime(int p)
{
/*
AKS素性测试表明如果
((x-1)^p-(x^p-1))模p==0,
那么p是素数
*/
int x;
布尔素数=真;
int[]arr=可展开多项式(x-1,p);

例如(int i=1;i
x
不是一个具有实际值的Java变量。它是多项式中的一个符号。在这里,您希望用Java表示一个实际多项式,而不是一个单独的值;因此,例如,对于x2+3 x+5,您可能希望将其表示为多项式系数的数组[1,3,5](虽然用相反的方法可能更好,[5,3,1],首先是系数x0——我认为这会使算法更平滑)。所以要表示x-1,需要一个
int[]
的值为[1,-1]或[-1,1]。您可以编写一个乘法方法,将两个多项式相乘;将a0+a1 x1+a2 x2…乘以b0+b1 x1+b2 x2,结果中x0的系数为a0 b0;x1的系数为a0 b1+a1 b0,x2的系数为a0 b2+a1 b1+a2 b0,依此类推。使用此方法,您可以将x-1表示为多项式,然后再进行多重运算将其自身叠加p次(使用多项式乘法方法)以得到多项式(x-1)p;然后减去xp和x0系数(以实现
-(x^p-1)
部分),并查看是否所有结果系数都可以被
p
整除

或者,不用做所有的多项式数学,你可以用(x-1)p的系数是二项式系数这一事实(也可以在Pascal三角形中找到),每切换一个符号。但无论如何,在测试p的可除性时,符号并不重要。因此,您可以通过计算所有二项式系数并查看它们是否可被p整除来执行测试。看哪一个表示相同的事情。要获得所有二项式系数,请从1开始,然后乘以
p
和di除以1,然后乘以
p-1
再除以2,然后乘以
p-2
再除以3,以此类推


当然,这样做实际上比仅仅通过奇数并查看
p
是否可以被其中任何一个整除要慢——这是检查素数的老方法。维基百科关于AKS测试的文章给出了一种算法,它实际上看起来要快一些,但它涉及到乘法阶和欧拉托蒂安(Euler's totien)等问题t函数,所以它太复杂了,无法在这里解释。

x
不是一个具有实际值的Java变量。它是多项式中的一个符号。在这里,您希望用Java表示一个实际多项式,而不是单个值;因此,例如,对于x2+3 x+5,您可能希望将其表示为一个数组[1,3,5],多项式的系数(虽然可能最好用相反的方式[5,3,1],首先是系数x0——我认为这会使算法更平滑)。因此,要表示x-1,需要一个
int[]
的值为[1,-1]或[-1,1]。您可以编写一个乘法方法,将两个多项式相乘;将a0+a1 x1+a2 x2…乘以b0+b1 x1+b2 x2,结果中x0的系数为a0 b0;x1的系数为a0 b1+a1 b0,x2的系数为a0 b2+a1 b1+a2 b0,依此类推。使用此方法,您可以将x-1表示为多项式,然后再进行多重运算将其自身叠加p次(使用多项式乘法方法)以得到多项式(x-1)p;然后减去xp和x0系数(以实现
-(x^p-1)
部分),并查看是否所有结果系数都可以被
p
整除

或者,不用做所有的多项式数学,你可以用(x-1)p的系数是二项式系数这一事实(也可以在Pascal三角形中找到),每切换一个符号。但无论如何,在测试p的可除性时,符号并不重要。因此,您可以通过计算所有二项式系数并查看它们是否可被p整除来执行测试。看哪一个表示相同的事情。要获得所有二项式系数,请从1开始,然后乘以
p
和di除以1,然后乘以
p-1
再除以2,然后乘以
p-2
再除以3,以此类推


当然,这样做实际上比仅仅通过奇数并查看
p
是否可以被其中任何一个整除要慢——这是检查素数的老方法。维基百科关于AKS测试的文章给出了一种算法,它实际上看起来要快一些,但它涉及到乘法阶和欧拉托蒂安(Euler's totien)等问题t函数,所以这里解释起来太复杂了。

不幸的是,视频在很多方面都很容易误导人

Grime博士在视频中花了大部分时间描述的是方程(1)。它是引理2.1,也是中的方程(1)。它是在16世纪被知道的,是指数时间。事实上,它比简单的试验划分慢。除了纯粹的乐趣,实现它真的没有什么意义

格里姆博士知道这不是真正的AKS,并在结尾提到了“其他一些微妙的部分”,这实际上是AKS的全部观点。数百年来,成千上万的人都在研究这个方程,可能用不同的方法来证明它,可能把它与帕斯卡三角形之类的东西联系起来(如果你愿意的话,也可以是塔塔利亚三角、杨辉三角、卡亚姆三角、平加拉三角等等)。关于
public class Solution {
    public static void main(String[] args) 
    {
        Scanner scan = new Scanner(System.in);
        int n = scan.nextInt();
        System.out.println(isPrime(n));
    }
    private static boolean isPrime(int p)
    {
        /*
        AKS primality test says that if
        ((x-1)^p - (x^p-1)) mod p == 0,
        then p is a prime
        */
        int x;
        boolean prime=true;
        int[] arr = expandPolynomial(x-1, p);
        for (int i=1;i<arr.length-1; i++)
        {
            // arr[0] and arr[arr.length-1] omitted
            // due to the subtraction in the test
            if (arr[i] % p != 0)
            {
                prime = false; 
            }
        }
        return prime;
    }
    private static int[] expandPolynomial()
    {
        /* 
        return the coefficient of each term
        from the leading term to x^1;
        */
    }
}