Auxiliar de fatoração de Fermat


19

Gostaríamos de fatorar um semiprime . O objetivo deste desafio é encontrar dois pequenos números inteiros e tais que pode ser trivialmente fatorado com o método de Fermat, permitindo assim a deduzir facilmente os fatores de .u vNuvNuvNN

A tarefa

Dado um semiprime e um número inteiro positivo , definimos e como:k x yNkxy

y=x2-kN

x=kN
y=x2kN

Etapa # 1 - Encontrek

Primeiro, você precisa encontrar o menor valor possível de , para que seja um número quadrado ( também conhecido como quadrado perfeito).yky

Isso permite fatorar com uma única iteração do método de fatoração de Fermat . Mais concretamente, isso imediatamente leva a:kN

kN=(x+y)×(xy)

(Atualização: esta sequência agora é publicada como A316780 )

Etapa 2 - Fatorark

Você precisa encontrar os dois números inteiros positivos u e v modo que:

c u = x +

uv=k
dv=x-
cu=x+y
dv=xy

em que c e d são os factores primários de N .

Sumário

Sua tarefa é escrever um programa ou função que aceite como entrada e imprima ou produz e em qualquer ordem e formato razoável.u vNuv

Exemplo

Vamos considerarN=199163

Passo 1

O menor valor possível de é , o que fornece:40k40

y=28232-40×199163=7969329-7966520=2809=532kN=(2823+53)×(2823-53)kN=2876×2770

x=(40×199163)=2823
y=2823240×199163=79693297966520=2809=532
kN=(2823+53)×(282353)
kN=2876×2770

Passo 2

A fatoração correta de é , porque:k = 4 × 10kk=4×10

k N = ( 719 × 4 ) × ( 277 × 10 ) N = 719 × 277

kN=2876×2770
kN=(719×4)×(277×10)
N=719×277

Portanto, a resposta correta seria ou .[ 10 , 4 ][4,10][10,4]

Regras

  • Não é necessário aplicar estritamente as duas etapas descritas acima. Você é livre para usar qualquer outro método, desde que encontre os valores corretos de e .vuv
  • Você deve suportar todos os valores de até o tamanho máximo nativo de um número inteiro não assinado em seu idioma.uvN
  • A entrada é garantida como semiprime.
  • Isso é código-golfe, então a resposta mais curta em bytes vence.
  • As brechas padrão são proibidas.

Casos de teste

N          | k    | Output
-----------+------+------------
143        | 1    | [   1,  1 ]
2519       | 19   | [   1, 19 ]
199163     | 40   | [   4, 10 ]
660713     | 1    | [   1,  1 ]
4690243    | 45   | [   9,  5 ]
11755703   | 80   | [  40,  2 ]
35021027   | 287  | [   7, 41 ]
75450611   | 429  | [ 143,  3 ]
806373439  | 176  | [   8, 22 ]
1355814601 | 561  | [  17, 33 ]
3626291857 | 77   | [   7, 11 ]
6149223463 | 255  | [  17, 15 ]
6330897721 | 3256 | [  74, 44 ]

Implementação de exemplo

No trecho de código abaixo, a função é uma implementação não-bloqueada que recebe como entrada e retorna e .N u vfNuv

Apenas para fins ilustrativos, o trecho de código também inclui a função que recebe , e como entrada e calcula os fatores de em .N u v N O ( 1 )gNuvNO(1)


Temos a garantia de que a entrada Nserá de fato um semiprime?
Greg Martin

@GregMartin Sim, você é.
Arnauld

Respostas:


8

Mathematica, 81 79 bytes

Agradecemos a Martin Ender por economizar 2 bytes!

(c=Ceiling;For[j=0;z=E,c@z>z,p=(x=c@Sqrt[j+=#])+{z=Sqrt[x^2-j],-z}];p/#~GCD~p)&

Função pura tomando um semiprime como entrada e retornando um par ordenado de números inteiros positivos. O Forloop implementa o procedimento exato descrito na pergunta (usando #para a entrada no lugar de n), com xcomo definido lá, embora armazenemos em j = k*nvez de ksi e em z=Sqrt[y]vez de ysi mesmo. Também calculamos p={x+z,x-z}dentro do Forloop, que acaba economizando um byte (como na sétima tentativa). Então os dois fatores desejados são (x+z)/GCD[#,x+z]e (x-z)/GCD[#,x-z], que a expressão concisa p/#~GCD~pcalcula diretamente como um par ordenado.

Curiosidades: queremos fazer um loop até que zseja um número inteiro; mas como Ceilingjá usaremos no código, ele economiza dois bytes !IntegerQ@zpara definir c=Ceiling(que custa quatro bytes, como sabem os jogadores do Mathematica) e depois testar se c@z>z. Temos que inicializar zpara algo, e é melhor que algo não seja um número inteiro para que o loop possa iniciar; felizmente, Eé uma escolha concisa.


4

JavaScript (ES7), 86 81 bytes

n=>(g=k=>(y=(n*k)**.5+1|0,y+=(y*y-n*k)**.5)%1?g(k+1):n*u++%y?g(k):[--u,k/u])(u=1)

Editar: salvou 4 bytes graças a @Arnauld.


4

Python 2, 127 121 117 111 107 104 101 99 bytes

-1 byte graças a Neil e -3 bytes graças a ovs

N=input()
k=u=1;p=m=.5
while p%1:p=1+(k*N)**m//1;p+=(p*p-k*N)**m;k+=1
while N*u%p:u+=1
print~-k/u,u

Experimente Online!

Curiosidades:

pé inicializado para .5que a condição do loop seja verdadeira na primeira iteração. Observe que é mais curto armazenar p(como x+ sqrt(y)) do que armazenar cada um xe yseparadamente.


x*xem vez de x**2?
194 Neil

@ Neil Sim, é claro. Graças
matemática viciado em

1

Axioma, 131 115 bytes

v(x)==floor(x^.5)::INT;r(n)==(k:=0;repeat(k:=k+1;x:=1+v(k*n);y:=v(x*x-k*n);x^2-y^2=k*n=>break);[w:=gcd(k,x+y),k/w])

A função que resolveria a questão é r (n) acima. ungolf e teste

vv(x)==floor(x^.5)::INT    

--(x-y)*(x+y)=k*n
rr(n)==
  k:=0
  repeat
     k:=k+1
     x:=1+vv(k*n)
     y:=vv(x*x-k*n)
     x^2-y^2=k*n=>break
  [w:=gcd(k,x+y),k/w]


(4) -> [[i,r(i)] for i in [143,2519,199163,660713,4690243,11755703]]
   (4)
   [[143,[1,1]], [2519,[1,19]], [199163,[4,10]], [660713,[1,1]],
    [4690243,[9,5]], [11755703,[40,2]]]
                                                      Type: List List Any
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.