计算克罗内克符号


9

这里这里的相关链接,但是这里是简短的版本:

您有两个整数的输入,ab介于负无穷大和无穷大之间(尽管如有必要,我可以限制范围,但函数仍必须接受负无穷大)。

Kronecker符号的定义

您必须返回Kronecker符号(a|b)进行输入,a并且b在哪里

(a|b) = (a|p_1)^e_1 * (a|p_2)^e_2 * ... * (a|p_n)^e_n

在那里b = p_1^e_1 * p_2^e_2 * ... * p_n^e_n,并p_ie_i在的因式分解素数和指数b

对于奇素数p(a|p)=a^((p-1)/2) (mod p)定义在这里

对于b == 2(n|2)={0 for n even; 1 for n odd, n=+/-1 (mod 8); -1 for n odd, n=+/-3 (mod 8)

对于b == -1(n|-1)={-1 for n<0; 1 for n>0

如果a >= b(a|b) == (z|b)在那里z == a % b。依此性质(如此此处所述)abif 的二次残基z,即使a >= b

(-1|b)= 1如果b == 0,1,2 (mod 4)-1如果b == 3 (mod 4)(0|b)0除了(0|1)它是1,因为(a|1)总是1和负面a(-a|b) == (-1|b) * (a|b)

Kronecker符号-1, 0 or 1的输出始终为,其中输出0if ab具有任何公因子。如果b是奇素数,(a|b) == 1如果a二次余数 MOD b,并且-1如果是它不是一个二次剩余。

规则

  • 您的代码必须是程序或函数。

  • 输入必须按顺序a b

  • 输出必须是-101

  • 这就是代码编写,所以您的代码不必高效,只需简短即可。

  • 没有内置函数可以直接计算Kronecker或相关的Jacobi和Legendre符号。其他内置功能(例如用于素数分解)是公平的游戏。

例子

>>> kronecker(1, 5)
1
>>> kronecker(3, 8)
-1
>>> kronecker(15, 22)
1
>>> kronecker(21, 7)
0
>>> kronecker(5, 31)
1
>>> kronecker(31, 5)
1
>>> kronecker(7, 19)
1
>>> kronecker(19, 7)
-1
>>> kronecker(323, 455625)
1
>>> kronecker(0, 12)
0
>>> kronecker(0, 1)
1
>>> kronecker(12, 0)
0
>>> kronecker(1, 0)
1
>>> kronecker(-1, 5)
1
>>> kronecker(1, -5)
1
>>> kronecker(-1, -5)
-1
>>> kronecker(6, 7)
-1
>>> kronecker(-1, -7)
1
>>> kronecker(-6, -7)
-1

这是一个复杂的功能,所以如果有任何不清楚的地方,请告诉我。



@MartinBüttner当我看到您的评论时,我正在编辑示例。我将禁止直接计算Kronecker,Jacobi或Legendre符号的内置函数,但其​​他任何函数(包括素因数分解函数)都应该是公平的游戏。
Sherlock15年

我不能完全确定为什么(31 | 5)给出1。不应该有二次残基,所以为什么不为-1?
Eumel,2015年

根据您链接的Wiki,7/19也应该为1,而19/7应该为-1
Eumel 2015年

3
如果解决方案必须正确处理负输入和零输入,则绝对应该为此添加一些测试用例。
马丁·恩德

Answers:


2

CJam(70字节)

{_g\zmf+f{:P2+"W>2*(
z1=
;1
7&4-z[0W0X0]=
P%P+P(2/#P%_1>P*-"N/<W=~}:*}

在线演示(使用Mathematica生成的测试案例)。

解剖

{               e# Anonymous function. Stack: a b
  _g\zmf+       e# Factorise b, with special treatment for negatives
                e# CJam also gives special treatment to 0 and 1
                e# Stack: e.g. a [-1 2 2 5]; or a [-1 1]; or a [0 0]; or a [1 2 2 5]
  f{            e# For each "prime" factor P, find (a|P)
    :P2+        e# Extract code for P from an array formed by splitting a string
    "W>2*(      e#   a -> (a|-1)
z1=             e#   a -> (a|0)
;1              e#   a -> (a|1)
7&4-z[0W0X0]=   e#   a -> (a|2)
P%P+P(2/#P%_1>P*-" e# a -> (a|P) for odd prime P
    N/<W=~      e# Split string and select appropriate element
  }
  :*            e# Multiply the components together
}

我发现了几种评估(a|2)相同字符数的方法,并选择使用显示方式最清晰的方法。

integer array <W= IMO是进行回退的一种非常优雅的方法:如果整数大于数组的长度,则选择最后一个元素。

其他的建议

这是令人失望的,对于奇素p直接费尔马风格(a|p)是如此短暂,因为有找到一个非常golfy方式(a|n)正奇怪n,我想用。基础是佐洛塔列夫的引理:

如果p是奇数质数且a是的整数互质数,p则Legendre符号(a|p)是排列的符号x -> ax (mod p)

Frobenius加强了这一点,

如果ab是互质的正奇整数,则Jacobi符号(a|b)是排列的符号x -> ax (mod b)

并由莱希(Lerch)到

如果b是一个正奇整数并且a是的整数互质数,b则Jacobi符号(a|b)是排列的符号x -> ax (mod b)

参见Brunyate和Clark,将Zolotarev-Frobenius方法扩展到二次互惠,The Ramanujan Journal 37.1(2014):25-50。

而且可以很容易地将其进一步加强(尽管我在文献中还没有看到)

如果b是正整数,a是整数,则Jacobi符号(a|b)是map的Levi-Civita符号x -> ax (mod b)

证明:如果a是互质的,b那么我们使用Zolotarev-Frobenius-Lerch; 否则,该图不是排列,并且Levi-Civita符号是0所需的。

这给出了雅可比符号计算

{_2m*{~>},@ff*\ff%::-:*g}

但是我需要一种特殊的处理方法(a|-1),这(a|2)意味着我还没有找到一种计算Kronecker符号的方法,这种方法使用这种方法会更短:单独分解和处理素数会更短。


4

Python 3中,747个 369 335字节

作为示例,答案只是打高尔夫球,让您对答案的外观有所了解。

是的,素数分解和游程编码位从Pyth道歉到isaacg

from itertools import*
def k(d,r):
 if d<0:a=-d;m=1
 else:a=d;m=0
 if r==1:return 1
 p=1;w=r;n=2;f=[]
 while n*n<=w:
  while w%n<1:w//=n;f+=n,
  n+=1
 if w>1:f+=w,
 z=[[k,len(list(g))]for k,g in groupby(f)]
 for i,j in z:
  if i==2:p*=pow(-1,(a*a-1)//8)
  x=pow(a,(i-1)//2,i)
  if x>1:x-=i
  p*=x**j
 if m:p*=pow(-1,(r-1)//2)
 return p

4
道歉已接受-我很高兴有人阅读了Pyth源代码。
isaacg 2015年

2

数学,169个 175 165字节

(1|-1)~k~0=_~k~1=1
_~k~0=0
a_~k~-1=If[a<0,-1,1]
a_~k~2=DirichletCharacter[8,2,a]
a_~k~p_/;PrimeQ@p=Mod[a^((p-1)/2),p,-1]
a_~k~b_:=1##&@@(a~k~#^#2&@@@FactorInteger@b)

2

LabVIEW,44字节LabVIEW原语

由于其对称性,如果a大于b,我将交换输入。

现在代表真实公式

像往常一样计数

对于真实的情况


不幸的是,(a|b) != (b|a)在所有情况下。在大多数情况下,是的,但并非全部。虽然如果您减少a mod b而不是交换它们会起作用。
Sherlock15年

由于我现在有外
植体

1
有什么办法可以测试吗?我不太了解LabView的工作原理。
Sherlock15年

这是一个好问题,我可以想到2种方法。首先,我可以构建一个.exe并将其发送给您,其次您可以获取一个labview测试版本,我可以向您发送vi或您可以从图片中重建它。
Eumel

7
这不是44个字节。如果定义的评分系统不基于文件的大小,则应使用字节以外的名称。
feersum

1

朱莉娅,195个字节

k(a,b)=b==0?a∈[1,-1]?1:0:b==1?1:b==2?iseven(a)?0:a%8∈[1,-1]?1:-1:b==-1?a<1?-1:1:isprime(b)&&b>2?a%b==0?0:a∈[i^2%b for i=0:b-1]?1:-1:k(a,sign(b))*prod(i->k(a,i)^factor(b)[i],keys(factor(b)))

这是一个递归函数k,它接受两个整数并返回一个整数。

取消高尔夫:

function k(a::Integer, b::Integer)
    if b == 0
        return a  [1, -1] ? 1 : 0
    elseif b == 1
        return 1
    elseif b == 2
        return iseven(a) ? 0 : a % 8  [1, -1] ? 1 : -1
    elseif b == -1
        return a < 1 ? -1 : 1
    elseif isprime(b) && b > 2
        return a % b == 0 ? 0 : a  [i^2 % b for i = 1:b-1] ? 1 : -1
    else
        p = factor(b)
        return k(a, sign(b)) * prod(i -> k(a, i)^p[i], keys(p))
    end
end

1

Haskell,286个字节

a#0|abs a==1=1|1<2=0
a#1=1
a#2|even a=0|mod a 8`elem`[1,7]=1|1<2=(-1)
a#b|b<0=a`div`abs a*a#(-b)|all((/=0).mod b)[2..b-1]=if elem n[0,1] then n else(-1)|1<2=product$map(a#)$f b where n=a^(div(b-1)2)`mod`b
f 1=[]
f n|n<0=(-1):f(-n)|1<2=let p=head$filter((==0).mod n)[2..n]in p:f(div n p)

可能没有完全优化,但是需要很大的努力。Kronecker符号定义为中缀函数a#b,即

*Main>323#455265 
1
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.