web-dev-qa-db-ja.com

最も簡単な方法で特定の累乗の単位桁を見つける方法

特定の数値の単位桁を見つける方法(例:3 power 2011)。この問題の答えを見つけるには、どのロジックを使用する必要がありますか?

10
user915435

ベース3の場合:

3^1 = 3
3^2 = 9
3^3 = 27
3^4 = 81
3^5 = 243
3^6 = 729
3^7 = 2187
...

つまり、単位の桁には4つの可能性しかなく、同じサイクルで繰り返されます。

オイラーの定理 の助けを借りて、これが任意の整数nに当てはまることを示すことができます。つまり、単位の桁は最大4つの連続した指数の後に繰り返されます。任意の積の単位の桁だけを見るのは、10を法とする乗算の​​余りを取ることと同じです。たとえば、次のようになります。

2^7 % 10 = 128 % 10 = 8 

また、任意の基数の場合、累乗の単位桁は基数自体の単位桁にのみ依存することを示すことができます(つまり、2013 ^ 2013の単位桁は3 ^ 2013と同じです)。

両方の事実を利用して、非常に高速なアルゴリズムを考え出すことができます( help -のおかげで、親切な許可を得て、はるかに高速なバージョンを提示できます)。

アイデアは次のとおりです。0〜9の任意の数に対して、最大4つの異なる結果が存在することがわかっているので、それらをルックアップテーブルに格納することもできます。

{ 0,0,0,0, 1,1,1,1, 6,2,4,8, 1,3,9,7, 6,4,6,4, 
  5,5,5,5, 6,6,6,6, 1,7,9,3, 6,8,4,2, 1,9,1,9 }

これは、4つにグループ化された0〜9の順序で考えられる結果です。アイデアは、べき乗n ^ aから

  • 最初に基本modを取得します10 =>:= i
  • テーブルのインデックス4*iに移動します(これはその特定の桁の開始オフセットです)
  • 指数mod4 =>:= offを取ります(オイラーの定理で述べられているように、4つの可能な結果しかありません!)
  • 結果を取得するには、off4*iに追加します

これを可能な限り効率的にするために、いくつかの調整が基本的な算術演算に適用されます。

  • 4を掛けることは、2を左にシフトすることと同じです( '<< 2')
  • a % 4の数字を取ることは、a&3と言うことと同じです(残りの%4を形成する1ビットと2ビットをマスクします)

Cのアルゴリズム:

static int table[] = {
    0, 0, 0, 0, 1, 1, 1, 1, 6, 2, 4, 8, 1, 3, 9, 7, 6, 4, 6, 4, 
    5, 5, 5, 5, 6, 6, 6, 6, 1, 7, 9, 3, 6, 8, 4, 2, 1, 9, 1, 9
};

int /* assume n>=0, a>0 */ 
unit_digit(int n, int a)
{
    return table[((n%10)<<2)+(a&3)];
}

最初のクレームの証明

観察すると、3 ^ xの単位の桁が4乗ごとに繰り返されていることがわかりました。主張は、これはどの整数にも当てはまるというものでした。しかし、これは実際にどのように証明されていますか?結局のところ、モジュラー演算を使用するのは非常に簡単です。単位の桁のみに関心がある場合は、10を法として計算を実行できます。これは、4つの指数の後に単位の桁が循環すると言うことと同じです。

a^4 congruent 1 mod 10

これが当てはまる場合、例えば

a^5 mod 10 = a^4 * a^1 mod 10 = a^4 mod 10 * a^1 mod 10 = a^1 mod 10

つまり、a ^ 5は、a ^ 1と同じ単位桁を生成します。

オイラーの定理 から

a^phi(10) mod 10 = 1 mod 10

ここで、phi(10)は、互いに素である1から10までの数です(つまり、それらのgcdは1に等しい)。 10未満の互いに素な数は1、3、7、および9です。したがってphi(10)= 4であり、これは本当にa^4 mod 10 = 1 mod 10であることを証明します。

証明する最後の主張は、底が10以上のべき乗の場合、底の単位の桁を見るだけで十分であるということです。基数がx> = 10であるとすると、x = x_0 + 10 * x_1 + 100 * x_2 + ...(基数10の表現)と言えます。

モジュラー表現を使用すると、実際にそれを簡単に確認できます

x ^ y mod 10
= (x_0 + 10*x_1 + 100*x_2 + ...) ^ y mod 10
= x_0^y + a_1 * (10*x_1)^y-1 + a_2 * (100*x_2)^y-2 + ... + a_n * (10^n) mod 10
= x_0^y mod 10  

ここで、a_iはx_0の累乗を含む係数ですが、積a_i *(10 * x_i)^ y-i全体が10で割り切れるため、最終的には関係ありません。

21
emboss

べき乗剰余 を確認する必要があります。必要なのは、m = 10でn ^ e(mod m)を計算することと同じです。これは、除算の余りを計算することと同じです。 n ^ eの10まで。

右から左へのバイナリメソッド が最も時間効率の良い方法であり、 最も簡単な 実装するのはそれほど難しくありません。ウィキペディアの擬似コードは次のとおりです。

function modular_pow(base, exponent, modulus)
    result := 1
    while exponent > 0
        if (exponent & 1) equals 1:
           result = (result * base) mod modulus
        exponent := exponent >> 1
        base = (base * base) mod modulus
    return result

その後、希望の底と指数に対してモジュラス= 10で呼び出すだけで、答えが得られます。

編集:さらに簡単な方法で、CPUに関しては効率的ではありませんが、メモリに関しては、ウィキペディアの記事の メモリ効率 セクションを確認してください。ロジックは十分に単純です。

function modular_pow(base, exponent, modulus)
    c := 1
    for e_prime = 1 to exponent 
        c := (c * base) mod modulus
    return c
8
Rafael Almeida

これを解決する適切な数学的方法があると確信していますが、あなたは最後の桁だけを気にし、理論的にはそれ自体を繰り返し乗算するすべての数値は最終的に繰り返しパターンを生成するはずなので(最後の桁だけを見るとき) )、最初の繰り返しを検出するまで乗算を実行してから、作成したパターンの適切な位置に指数をマッピングすることができます。

最後の桁だけを気にするので、パターンマッピングの構築を開始する前に、入力番号を1桁に切り捨てることで、さらに単純化できることに注意してください。これにより、最初または2番目の乗算でオーバーフローが発生する任意の大きな入力の場合でも、最後の桁を判別できます。

JavaScriptの基本的な例を次に示します。 http://jsfiddle.net/dtyuA/2/

ちなみに、3^2011の最後の桁は7です。

8
aroth

基数の10桁を連続する累乗して得られた各結果の最後の桁を調べることから始めることができます。

d      d^2    d^3    d^4    d^5    d^6    d^7    d^8    d^9 (mod 10)
---    ---    ---    ---    ---    ---    ---    ---    ---
0      0      0      0      0      0      0      0      0
1      1      1      1      1      1      1      1      1
2      4      8      6      2      4      8      6      2
3      9      7      1      3      9      7      1      3
4      6      4      6      4      6      4      6      4
5      5      5      5      5      5      5      5      5
6      6      6      6      6      6      6      6      6
7      9      3      1      7      9      3      1      7
8      4      2      6      8      4      2      6      8
9      1      9      1      9      1      9      1      9

すべての場合において、最後の桁が4つ以下の異なる値を循環していることがわかります。この事実を使用し、nが非負の整数であり、pが正の整数であると仮定すると、結果をかなり直接計算できます(Javascriptなど)。

function lastDigit(n, p) {
    var d = n % 10;
    return [d, (d*d)%10, (d*d*d)%10, (d*d*d*d)%10][(p-1) % 4];
}

...またはさらに簡単に:

function lastDigit(n, p) {
    return Math.pow(n % 10, (p-1) % 4 + 1) % 10;
}

lastDigit(3, 2011)
/* 7 */

2番目の関数は最初の関数と同等です。べき乗を使用していても、9の4乗(6561)を超える数値では機能しないことに注意してください。

3
WReach

このタイプの質問を解決するための鍵は オイラーの定理 にあります。

この定理により、aとmが互いに素である場合に限り、a ^ phi(m)mod m = 1 modmと言うことができます。つまり、aとmは均等に分割されません。これが事実である場合(そしてあなたの例ではそうです)、プログラミングなしで紙の上で問題を解決することができます。

あなたの例のように、3 ^ 2011の単位桁を解いてみましょう。これは3 ^ 2011 mod10と同等です。

最初のステップは、3と10が互いに素であることを確認することです。それらは均等に分割されないので、オイラーの定理を使用できます。

また、10の場合の totient 、つまりphi値を計算する必要があります。10の場合は4です。100phiの場合は40、1000は4000などです。

オイラーの定理を使用すると、3 ^ 4 mod 10 = 1であることがわかります。次に、元の例を次のように書き直すことができます。

3^2011 mod 10 = 3^(4*502 + 3) mod 10 = 3^(4*502) mod 10 + 3^3 mod 10 = 1^502 * 3^3 mod 10 = 27 mod 10 = 7

したがって、3 ^ 2011の最後の桁は7です。

ご覧のとおり、これにはプログラミングはまったく必要ありませんでした。私はこの例を一枚のスクラッチペーパーで解決しました。

3
samoz

あなたのpplは単純なことを複雑にしています。

Uがabc ^ xyzの単位桁を調べたいとします。

divide the power xyz by 4,if remainder is 1 ans is c^1=c.
 if xyz%4=2 ans is unit digit of  c^2.
 else if xyz%4=3 ans is unit digit of  c^3.

 if xyz%4=0 
 then we need to check whether c is 5,then ans is 5
  if c is even ans is 6
 if c is odd (other than 5 ) ans is 1.
1
user1112782

これは、基数の倍数ではない数値に対して機能するトリックです(基数10の場合、2または5の倍数にすることはできません)。基数3を使用しましょう。検索しようとしているのは3 ^ 2011 mod 10. 3 ^ 1から始まり、最後の桁が1の累乗が見つかるまで、3の累乗を見つけます。3の場合、3 ^ 4 = 81になります。元のパワーを(3 ^ 4)^ 502 * 3 ^ 3と書きます。モジュラー算術を使用すると、(3 ^ 4)^ 502 * 3 ^ 3は1 ^ 502 * 3 ^ 3と合同になります(最後の桁は同じです)。したがって、3 ^ 2011と3 ^ 3の最後の桁は同じで、7です。

これは、一般的にそれを説明するためのいくつかの擬似コードです。これにより、基数Bのb ^ nの最後の桁が見つかります。

// Find the smallest power of b ending in 1.
i=1
while ((b^i % B) != 1) {
    i++
}
// b^i has the last digit 1

a=n % i
// For some value of j, b^n == (b^i)^j * b^a, which is congruent to b^a
return b^a % B

Bの累乗が1で終わらない場合は、無限ループを防ぐように注意する必要があります(基数10では、2または5の倍数は機能しません)。

0
user916576

この場合の繰り返しセットを見つけてください。これは3,9,7,1であり、永遠に同じ順序で繰り返されます。2011を4で割ると、リマインダー3が得られます。これが繰り返しの3番目の要素です。セットする。これは、特定の番号を見つける最も簡単な方法です。たとえば、3 ^ 31を要求された場合、31/4のリマインダーは3であるため、7は単位桁です。 3 ^ 9の場合、9/4は1であるため、単位は3になります。3^ 100の場合、単位は1になります。

0
siva

以下は、累乗とその累乗の3の単位桁の表です。
0 1
1 3
2 9
3 7
4 1
5 3
6 9
7 7

この表を使用すると、単位桁が1、3、9、7であり、シーケンスがこの順序で繰り返され、3の累乗が大きいことがわかります。このロジックを使用すると、(3累乗2011)の単位桁が7であることがわかります。 。一般的な場合にも同じアルゴリズムを使用できます。

0
Andrei Bozantan

数値と指数が分かれている場合は簡単です。

N1を数値、n2を累乗とします。そして**は力を表します。

n1> 0と仮定します。

%はモジュロ除算を意味します。

擬似コードは次のようになります

def last_digit(n1, n2)
  if n2==0 then return 1 end
  last = n1%10
  mod = (n2%4).zero? ? 4 : (n2%4)
  last_digit = (last**mod)%10
end

説明:

累乗の最後の桁を決定するので、数値の最後の桁だけを考慮する必要があります。各桁(0〜9)の累乗の最後の桁の可能性のカウントが最大で4であるのは、数学のプロパティです。

1)指数がゼロの場合、最後の桁は1になることがわかります。

2)数値(n1)の最後の桁を%10だけ取得します

3)指数(n2)の%4-出力がゼロの場合、n2をゼロにすることはできないため、これを4と見なす必要があります。 %4がゼロ以外の場合、%4の値を考慮する必要があります。

4)現在は最大9 ** 4です。これは、コンピューターが計算するのは簡単です。その数の%10を取ります。あなたは最後の桁を持っています。

0
InQusitive