100000000003を法とする整数の逆数を計算します


21

タスクは次のとおりです。任意の方法でコードに与えられた整数xxモジュロ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それはうまく見えます。

タグ:制限されたコード?
フェリペナルディバティスタ

1
何が特別なの100000000003ですか?(ただ疑問に思う)
NoOneIsHere

1
@Lembikその場合、質問でy <100000000003という要件に言及できますか?
isaacg

回答:


16

Pyth、24バイト

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

テストスイート

これは、a ^(p-2)mod p = a ^ -1 mod pという事実を使用しています。

最初に、mod 100000000003の特定のケースに対して、モジュラスを手動で再実装します。式を使用します。a mod b = a - (a/b)*bここ/で、floored divisionです。10^11 + 3コードを使用して係数を生成し、+3^T11保存してからJ、これと上記の式を使用して、b mod 100000000003を計算し-b*/bJ+3^T11Jます。この関数は次のように定義されるyL

次に、入力から始めて、10乗して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ヨハンセン

9

ハスケル118の 113 105 101バイト

このソリューションに触発されました

-12ØrjanJohansenから

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、あなたが作ることができる演算子はインラインをそこに。(3)重複することを犠牲にして、トリックによって高価なものを取り除くことができます。オンラインでお試しください!!ywherelastz
Ørjanヨハンセン

今、それらは素晴らしいトリックです!
バルタヴェル

ああ、|e==0=aその厄介な複製を取り除きます。
Ørjanヨハンセン

6

Brachylog、22バイト

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

オンラインでお試しください!

これは1000000、わずかに異なる(より長い)バージョンのコードで、正確に2倍速い(İ正と負の両方の代わりに正の値のみをチェックする)ために約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残念ながら、この速度はの値に完全に依存してİいるため、大きな製品の場合はまだかなり遅いです。
17

質問を更新しました。コードの所要時間は常に30分未満ですか?

6

Python、53 51 49 58 53 49バイト

-2 orlpおかげバイト
-2 officialaimmおかげバイト
-4フェリペナルディBatistおかげバイト
-3 isaacgおかげバイト
Ørjanヨハンセンのおかげ-1バイト
-2フェデリコPoloniおかげバイト

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

オンラインでお試しください!

これを理解するのに約30分かかりました。私の解決策は、1にmodする最初の数から始めることです。この数は1です。xで割り切れる場合、yはその数をxで割ったものです。そうでない場合は、この数値に10000000003を加算して、mod 1000000003が1に等しい2番目の数値を見つけて繰り返します。


1にmodする最初の数は1
...-orlp

@orlp lolありがとう。それで2バイト節約できました:)
ザカリーコットン

興味深いことに、TIOではこれはすべてのテストケースで高速ですが、少しランダムなキーボードを叩くと421385994タイムアウトになります。
Ørjanヨハンセン

@ØrjanJohansen良い探索。

1
b一度だけ必要な場合は、ハードコーディングしてみませんか?
フェデリコポロニ

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)

モジュロは次の計算により実装されます:

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

オイラーの定理と2進べき乗法に基づく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。x86-64 Windowsでは32ビットです。 longただし、x86-64 Linux(およびSystemV ABIを使用する他のOS)では64ビットタイプです。したがって、完全に移植可能にするには、C ++ 11以降、少なくとも64ビットでlong longあることが保証されているを使用する必要があります。
ピーターコーデス

__int128_tこれは標準のC ++ではないようです。gcc拡張機能のようです。これを言語(C ++ 11 + gcc)として記述した方がいいでしょう。
フェリックスドンベック

3
これはC ++のエキスパートサイトではありません。誰も気付かないことを願っています。
SteelRaven

@PeterCordes Codeゴルフは、ポータブルである必要はなく、整形式である必要さえありません。1つの実装で作業する必要があります。
アシェプラー

1
@aschepler:私は「あなたが言った理由である、知っているだろう必要があります」。誰かがそれを試してトラブルに遭遇した場合に備えて、どのプラットフォームで動作する/しないのかを指摘することは有用だと思いました。
ピーターコーデス

4

Mathematica、49バイト

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

これを実行するにはどれくらい時間がかかりますか?

私のコンピュータ上の0.001s未満(ケース2 ^ 40-1)
Keyuガン


1

ルビー、58バイト

ブルートフォースソリューションの計時を終える間、現在のところFermatの小さな定理のisaacgのアプリケーションを使用しています。

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