คำนวณค่าผกผันของโมดูโลจำนวนเต็ม 100000000003


21

ภารกิจมีดังต่อไปนี้ ได้รับจำนวนเต็มx(เช่นที่xโมดูโล100000000003ไม่เท่ากับ0) นำเสนอให้กับรหัสของคุณในทางที่คุณพบว่าสะดวกเอาท์พุทจำนวนเต็มอีกเพื่อให้y < 100000000003(x * y) mod 100000000003 = 1

รหัสจะต้องใช้เวลาน้อยกว่า 30 นาทีในการทำงานบนเครื่องเดสก์ท็มาตรฐานสำหรับการใด ๆการป้อนข้อมูลดังกล่าวว่าx|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? (เพียงแค่สงสัย)
NoOneIsHere

1
@ Lembik ในกรณีนี้คุณสามารถพูดถึงข้อกำหนดที่ y <100000000003 ในคำถามได้หรือไม่
isaacg

คำตอบ:


16

Pyth, 24 ไบต์

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

ชุดทดสอบ

สิ่งนี้ใช้ความจริงที่ว่า ^ (p-2) mod p = a ^ -1 mod p

ก่อนอื่นฉันปรับใช้โมดูลัสด้วยตนเองสำหรับกรณีเฉพาะของ mod 100000000003 ฉันใช้สูตรa mod b = a - (a/b)*bซึ่ง/เป็นส่วนที่เป็นพื้น ฉันสร้างโมดูลัสที่มี10^11 + 3การใช้รหัส+3^T11แล้วบันทึกไว้ในJแล้วใช้นี้และสูตรข้างต้นในการคำนวณข mod 100000000003 -b*/bJ+3^T11Jกับ ฟังก์ชั่นนี้ถูกกำหนดให้เป็นด้วยyL

ต่อไปฉันเริ่มด้วยอินพุตจากนั้นนำไปที่กำลังสิบและลด mod 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

Haskell , 118 113 105 101 ไบต์

แรงบันดาลใจจากโซลูชันนี้

-12 จากØrjan Johansen

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]

ลองออนไลน์!

Haskell , 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จากนั้นคุณสามารถทำให้ไม่ใช่ -operator ใกล้เคียงเป็นมัน (3) คุณสามารถกำจัดของที่มีราคาแพงโดยเคล็ดลับที่ค่าใช้จ่ายของการทำซ้ำ ลองออนไลน์! !ywherelastz
Ørjan Johansen

ตอนนี้เป็นเทคนิคที่ดี!
bartavelle

โอ้และ|e==0=aกำจัดการทำซ้ำที่น่ารำคาญ
Ørjan Johansen

6

Brachylogขนาด 22 ไบต์

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

ลองออนไลน์!

การดำเนินการนี้ใช้เวลาประมาณ 10 นาทีสำหรับ1000000โค้ดที่แตกต่างกันเล็กน้อย (และนานกว่า) ซึ่งเร็วกว่าสองเท่า (ตรวจสอบเฉพาะค่าบวกของİแทนที่จะเป็นทั้งค่าบวกและค่าลบ) ดังนั้นควรใช้เวลาประมาณ 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 ความเร็วของสิ่งนี้น่าเสียดายที่ขึ้นอยู่กับมูลค่าของİมันดังนั้นมันจึงค่อนข้างช้าสำหรับผลิตภัณฑ์ขนาดใหญ่
ทำให้เสียชีวิต

อัปเดตคำถาม รหัสของคุณใช้เวลาน้อยกว่า 30 นาทีเสมอหรือไม่

6

Python, 53 51 49 58 53 49 ไบต์

-2 ไบต์ขอบคุณ orlp
-2 ไบต์ขอบคุณ officialaimm
-4 ไบต์ขอบคุณ Felipe Nardi Batist
-3 ไบต์ขอบคุณ isaacg
-1 ไบต์ขอบคุณØrjan Johansen
-2 ไบต์ขอบคุณ Federico Poloni

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 ขอบคุณมาก นั่นช่วยฉันได้ 2 ไบต์ :)
Zachary Cotton

สิ่งที่น่าสนใจใน TIO นี้รวดเร็วสำหรับทุกกรณีทดสอบ แต่การกระแทกคีย์บอร์ดแบบสุ่มเล็กน้อยทำให้ฉัน421385994หมดเวลา
Ørjan Johansen

@ ØrjanJohansenเก่งมาก

1
หากคุณต้องการbเพียงครั้งเดียวทำไมไม่ hardcoding มัน?
Federico Poloni

5

JavaScript (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)

Modulo นำมาใช้โดยการคำนวณ:

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

เนื่องจากความฉลาดทางยังต้องการด้วยการทำเช่นนั้นทำให้รู้สึกจริง

กรณีทดสอบ


คุณต้องปูพื้น 64 บิตในการเกิดครั้งล่าสุดเพื่อให้คุณสามารถแทนที่อันอื่นด้วย 0 | x / y และลบการประกาศ
Oki

5

C ++ 11 (GCC / Clang, Linux), 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 ++ ต้องlongมีอย่างน้อย 32 บิตดังนั้นจึงไม่สามารถระงับ1e11 + 3ได้ มันเป็นแบบ 32 บิตบน x86-64 Windows longเป็นชนิด 64 บิตบน x86-64 Linux (และ OS อื่น ๆ ที่ใช้ SystemV ABI) ดังนั้นที่จะพกพาอย่างเต็มที่คุณจะต้องใช้long longซึ่งจะรับประกันว่าจะมีอย่างน้อย 64 บิตตั้งแต่ C
Peter Cordes

__int128_tดูเหมือนจะไม่เป็นมาตรฐาน C ++ ดูเหมือนว่าจะเป็นส่วนขยาย gcc มันจะเจ๋งถ้าคุณระบุว่านี่เป็นภาษา (C ++ 11 + gcc)
เฟลิกซ์ดอมเบ

3
นี่ไม่ควรจะเป็นเว็บไซต์ผู้เชี่ยวชาญของ C ++ ฉันหวังว่าจะไม่มีใครสังเกตเห็น
SteelRaven

@PeterCordes Code golf ไม่จำเป็นต้องพกพาหรือมีรูปแบบที่ดีเพียงแค่ต้องการทำงานในการติดตั้งเพียงครั้งเดียว
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 ไบต์

ใช้การประยุกต์ใช้ทฤษฎีบทเล็ก ๆ ของแฟร์มาต์ในขณะนี้ในขณะที่ฉันเสร็จสิ้นการกำหนดเวลาวิธีการแก้ปัญหากำลังดุร้าย

->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.