C++
 Computer >> コンピューター >  >> プログラミング >> C++

C++で巨大な数のa^bの最後の桁を効率的に求める方法

この問題では、2つの数 a と b が与えられ、巨大な数になる a^b の最後の桁(下一桁)を求めることが課題となります。a^b は桁あふれするほど大きな値になる可能性があるため、べき乗を直接計算するのではなく、工夫された方法で下一桁だけを導き出します。

問題の例

入力: a = 4、b = 124

出力: 6

解説:

a^b の実際の値は 4.523128486 × 1074 という莫大な数ですが、その最後の桁は「6」です。

解法のアプローチ

この問題を解くカギとなるのは、「ある数の冪乗の下一桁は、指数が4回ごとに同じパターンで循環する」という性質です。

さらに、冪乗の最後の桁は底の最後の桁だけで決まるため、a 全体を使う必要はなく、a の下一桁だけで計算できます。

以上より、答えは次の式で求められます。

(a の最後の桁) ^ (b % 4) の最後の桁

なお、b % 4 が 0 になった場合には、代わりに指数として 4 を使用します(サイクルがちょうど一周完了するためです)。

実装プログラム

以下は、この解法の動作を示すC++プログラムです。a と b を文字列として受け取ることで、標準の整数型に収まらないような巨大な数にも対応しています。

#include <bits/stdc++.h>
using namespace std;

// 巨大な数(文字列)を a で割った余りを計算する
int calcModulus(char b[], int a)
{
    int mod = 0;

    for (int i = 0; i < strlen(b); i++)
        mod = (mod * 10 + b[i] - '0') % a;

    return mod;
}

int calcLastDigitInExpo(char a[], char b[]) {

    int len_a = strlen(a), len_b = strlen(b);

    // 0^0 のケース
    if (len_a == 1 && len_b == 1 && b[0] == '0' && a[0] == '0')
        return 1;
    // 指数が 0 のケース
    if (len_b == 1 && b[0] == '0')
        return 1;
    // 底が 0 のケース
    if (len_a == 1 && a[0] == '0')
        return 0;

    int exponent = (calcModulus(b, 4) == 0) ? 4 : calcModulus(b, 4);
    int base = a[len_a - 1] - '0';
    int result = pow(base, exponent);
    return result % 10;
}

int main()
{
    char a[] = "559", b[] = "4532";
    cout<<"The last digit in of the value is "<<calcLastDigitInExpo(a, b);
    return 0;
}

出力結果

The last digit in of the value is 1

コードのポイント

  • calcModulus 関数: 文字列として表現された巨大な数 b を1桁ずつ処理しながら、4 で割った余りを求めます。これにより、通常の整数型では扱えない大きな数でも正確に b % 4 を計算できます。
  • エッジケースへの対応: 0^0 および指数が 0 の場合は 1 を、底が 0 の場合は 0 を返すように処理されています。
  • 高速な計算: 底としては a の最後の桁しか使わず、指数も 1〜4 の範囲に限定されるため、a や b がどれほど巨大でも計算時間はほぼ一定です。
  1. 配列の要素の積の最初の桁を求めるC++プログラム

    はじめにこの記事では、与えられた配列のすべての要素を掛け合わせた積の、最初の桁(最上位の桁)を求めるプログラムについて解説します。例として、次のような配列が与えられたとします。arr = {12, 5, 16}これらの要素の積は、12 × 5 × 16 = 960 となります。したがって、求める結果、つまり積の最初の桁は「9」になります。アルゴリズム変数 prod を 1 で初期化するループを使い、配列の各要素を順番に prod に掛けていくprod が 10 以上である間、prod を 10 で割り続ける残った一桁の値が、積の最初の桁となるサンプルコード#include <bits/s

  2. 大きな数の階乗を求めるC++プログラムの書き方

    階乗とは、1からその数までのすべての整数を掛け合わせた値のことです。たとえば 5! = 5×4×3×2×1 = 120 となります。以下に、階乗を求めるC++プログラムの例を示します。 プログラム例 #include <iostream> using namespace std; unsigned long long int fact(unsigned long long int n) { if (n == 0 || n == 1) return 1; else return n * fact(n - 1); } int mai