정수 모듈로의 역수를 계산합니다 100000000003


21

작업은 다음과 같습니다. 정수 감안할 때 x(되도록 x모듈이 100000000003아닌 같음 0당신이 편리하게 찾을 수있는 방법으로 코드에 제출), 출력 또 다른 정수 y < 100000000003그 정도 (x * y) mod 100000000003 = 1.

표준 데스크탑 시스템에서 다음x 과 같은 입력에 대해 코드를 실행하는 데 30 분 미만이 소요됩니다 |x| < 2^40.

테스트 사례

입력 : 400000001. 출력 : 65991902837

입력 : 4000000001. 출력 : 68181818185

입력 : 2. 출력 : 50000000002

입력 : 50000000002. 출력 : 2.

입력 : 1000000. 출력 : 33333300001

제한 사항

모듈로 산술 (또는이 역 연산)을 수행하는 라이브러리 나 내장 함수를 사용할 수 없습니다. 이것은 자신 a % b을 구현 하지 않고 는 할 수 없다는 것을 의미합니다 %. 그러나 다른 모든 비 모듈로 산술 내장 함수를 사용할 수 있습니다.

비슷한 질문

질문 과 유사 하지만 여전히 관심을 가질 정도로 충분히 희망적입니다.


그렇다면 a- (a / b) * b는 괜찮습니까?
user253751

@immibis 괜찮아 보인다.

태그 : 제한된 코드?
Felipe Nardi Batista

1
특별한 점은 무엇입니까 100000000003? (그냥 궁금해)
NoOneIs 여기

1
@Lembik이 경우 질문에서 y <100000000003이라는 요구 사항을 언급 할 수 있습니까?
isaacg

답변:


16

Pyth, 24 바이트

L-b*/bJ+3^T11Jy*uy^GT11Q

테스트 스위트

이것은 a ^ (p-2) mod p = a ^ -1 mod p라는 사실을 사용합니다.

먼저, 수동으로 구현할 계수, 개조 100000000003.의 특정 경우에 대해 화학식 I의 사용 a mod b = a - (a/b)*b, /바닥의 분할이다. 10^11 + 3코드를 사용하여 모듈러스를 생성 한 +3^T11다음 저장 J한 다음이 수식과 위의 공식을 사용하여 b 모드 100000000003을 계산 -b*/bJ+3^T11J합니다. 이 함수는 다음과 같이 정의된다 yL.

다음으로 입력으로 시작한 다음 10 번째 거듭 제곱으로 가져 와서 모드 100000000003을 줄이고이 11 번 반복합니다. y^GT각 단계에서 실행되는 코드이며 uy^GT11Q입력부터 시작하여 11 번 실행됩니다.

이제 Q^(10^11) mod 10^11 + 3,을 원 하고을 Q^(10^11 + 1) mod 10^11 + 3입력에 곱하고 마지막으로 한 번 *mod 100000000003을 줄이고 y출력합니다.


참으로 아주 좋은!

테스트 케이스를 강화하기에는 너무 늦었다 고 생각합니다.

1
@Lembik 어쨌든 할 것이지만 의견은 다를 수 있습니다. 그것은 당신의 도전입니다, 당신이 원하는 방식으로 작동하게하십시오.
isaacg

질문이 작성되는 방식으로 최종 축소를 취소 할 수는 있지만 결과 <100000000003이 필요한지 여부를 명확하게 요청했습니다.
Ørjan Johansen

9

하스켈 , 118 113 105 101 바이트

이 솔루션 에서 영감을 얻었습니다 .

Ørjan Johansen에서 -12

p=10^11+3
k b=((p-2)?b)b 1
r x=x-div x p*p
(e?b)s a|e==0=a|1<2=(div e 2?b$r$s*s)$last$a:[r$a*s|odd e]

온라인으로 사용해보십시오!

하스켈 , 48 바이트

이 솔루션을 다시 작성 하십시오 . 테스트 벡터에는 충분히 빠르지 만이 솔루션은 다른 입력에 비해 너무 느립니다.

s x=until(\t->t-t`div`x*x==0)(+(10^11+3))1`div`x

온라인으로 사용해보십시오!


대박! 나는 제곱 접근법으로 지수를 좋아합니다.
isaacg

가장 짧은 해결책은 온라인으로 사용해보십시오! 그러나 나는 그것의 성능이 수용 가능하다고 생각하지 않습니다 ...
bartavelle

(1)이 만드는 짧다 g운영자 (e?b)a s|...당신이 전환하는 경우 (2) a그리고 s당신은 할 수 - 연산자와 인라인을 그것으로. (3) 당신은 비싼 제거 할 수 a로 복제의 비용으로, 트릭 . 온라인으로 사용해보십시오! !ywherelastz
Ørjan Johansen

이제 좋은 트릭입니다!
bartavelle

아, 그리고 |e==0=a그 성가신 복제를 제거합니다.
Ørjan Johansen

6

Brachylog , 22 바이트

∧10^₁₁+₃;İ≜N&;.×-₁~×N∧

온라인으로 사용해보십시오!

1000000정확히 두 배 더 빠른 코드의 약간 다른 (더 긴) 버전으로 약 10 분이 걸렸습니다 ( İ양수와 음수 대신 양수 값만 확인 ). 따라서 해당 입력을 완료하는 데 약 20 분이 소요됩니다.

설명

우리는 간단히 그것을 설명하고 Input × Output - 1 = 100000000003 × an integer제약 산술 Output이 우리를 찾 도록합니다.

∧10^₁₁+₃                   100000000003
        ;İ≜N               N = [100000000003, an integer (0, then 1, then -1, then 2, etc.)]
            &;.×           Input × Output…
                -₁         … - 1…
                  ~×N∧     … = the product of the elements of N

우리는 기술적으로 명시적인 라벨링이 필요 하지 않지만, 사용하지 않으면 케이스를 확인하지 않습니다 N = [100000000003,1](경우에 따라 쓸모가 없기 때문에). 2예를 들어 두 번째로 작은 정수를 찾아야하므로 입력이 매우 느릴 것 첫 번째 대신.


1
와우, 나는 그것을 풀기 위해 제약 연산을 기대하지 않았을 것입니다. 대박!
isaacg

1
@isaacg 이것의 속도는 불행히도의 값에 전적으로 의존 İ하기 때문에 큰 제품에서는 여전히 느립니다.
Fatalize

질문을 업데이트했습니다. 코드가 항상 30 분 미만입니까?

6

파이썬, 53 51 49 58 53 49 바이트

-2 바이트 orlp 덕분에
-2 바이트 officialaimm 덕분에
-4 바이트 Felipe Nardi Batist
덕분에 -3 바이트 isaacg 덕분에
-1 바이트 Ørjan Johansen
덕분에 -2 바이트 Federico Poloni 덕분에 -2 바이트

x=input()
t=1
while t-t/x*x:t+=3+10**11
print t/x

온라인으로 사용해보십시오!

이것을 알아내는 데 ~ 30 분이 걸렸습니다. 내 해결책은 1로 수정되는 첫 번째 숫자로 시작하는 것입니다.이 숫자는 1입니다. x로 나눌 수 있으면 y는 x로 나눈 숫자입니다. 그렇지 않으면이 숫자에 10000000003을 더하여 mod 1000000003이 1과 같은 두 번째 숫자를 찾아 반복하십시오.


1로 수정 될 첫 번째 숫자는 1입니다.
orlp

@orlp lol 감사합니다. 그것은 나를 2 바이트 절약했습니다 :)
Zachary Cotton

흥미롭게도 TIO에서는 모든 테스트 사례에서 빠르지 만 약간의 무작위 키보드 뱅킹으로 인해 421385994시간이 초과되었습니다.
Ørjan Johansen

트윗 담아 가기

1
b한 번만 필요한 경우 하드 코딩하지 않겠습니까?
Federico Poloni

5

자바 스크립트 (ES6) 153 143 141 바이트

math.stackexchange.com의이 답변에서 영감 을 얻었습니다 .

유클리드 알고리즘에 기반한 재귀 함수.

f=(n,d=(F=Math.floor,m=1e11+3,a=1,c=n,b=F(m/n),k=m-b*n,n>1))=>k>1&d?(e=F(c/k),a+=e*b,c-=e*k,f(n,c>1&&(e=F(k/c),k-=e*c,b+=e*a,1))):a+d*(m-a-b)

모듈로는 다음과 같은 컴퓨팅으로 구현됩니다.

quotient = Math.floor(a / b);
remainder = a - b * quotient;

몫도 필요하기 때문에 그렇게하는 것이 실제로 의미가 있습니다.

테스트 사례


마지막 발생시 64 비트 플로어링 만 필요하므로 다른 것을 0 | x / y로 바꾸고 선언을 제거 할 수 있습니다.
Oki

5

C ++ 11 (GCC / 연타 리눅스) 104 102 바이트

using T=__int128_t;T m=1e11+3;T f(T a,T r=1,T n=m-2){return n?f(a*a-a*a/m*m,n&1?r*a-r*a/m*m:r,n/2):r;}

https://ideone.com/gp41rW

오일러의 정리와 이진 지수를 기반으로 ungolfed.

using T=__int128_t;
T m=1e11+3;
T f(T a,T r=1,T n=m-2){
    if(n){
        if(n & 1){
            return f(a * a - a * a / m * m, r * a - r * a / m * m, n / 2);
        }
        return f(a * a - a * a / m * m, r, n / 2);
    }
    return r;
}

ISO C ++는 long32 비트 이상이면되므로 반드시 보유 할 수는 없습니다 1e11 + 3. x86-64 Windows에서 32 비트입니다. long그러나 x86-64 Linux (및 SystemV ABI를 사용하는 다른 OS)의 64 비트 유형입니다. 따라서 이식성 long long좋으려면 C ++ 11 이후로 64 비트 이상을 보장 하는 을 사용해야 합니다.
Peter Cordes

__int128_t표준 C ++ 인 것처럼 보이지 않으며 gcc 확장 인 것 같습니다.이 언어를 언어 (C ++ 11 + gcc)로 말하면 멋질 것입니다.
Felix Dombek

3
이 사이트는 C ++ 전문가 사이트가 아닙니다. 아무도 눈치 채지 않기를 바랍니다.
SteelRaven

@PeterCordes Code 골프는 휴대가 가능하거나 형식이 정교하지 않아도되며 한 가지 구현으로 작업하면됩니다.
aschepler

1
@aschepler : 나는 "당신이 말한 이유는, 알 것입니다 필요합니다." 누군가가 그것을 시도하고 문제를 겪을 경우, 작동하지 않을 플랫폼을 지적하는 것이 유용하다고 생각했습니다.
Peter Cordes

4

Mathematica, 49 바이트

x/.FindInstance[x#==k(10^11+3)+1,{x,k},Integers]&

실행하는 데 시간이 얼마나 걸립니까?

내 컴퓨터에서 0.001s 미만 (2 ^ 40-1의 경우)
Keyu Gan


1

루비 , 58 바이트

내가 무차별 대입 솔루션의 타이밍을 마무리하는 동안 isaacg의 Fermat의 작은 정리 적용을 사용합니다.

->n,x=10**11+3{i=n;11.times{i**=10;i-=i/x*x};i*=n;i-i/x*x}

47 바이트하지만 현재 브 루트 포스 버전 이 될 수는 있다 너무 느린 :

->n,x=10**11+3{(1..x).find{|i|i*=n;i-i/x*x==1}}

온라인으로 사용해보십시오!

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.