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

毎回Bで割り切れるようにAにN桁を追加するアルゴリズム

問題概要

整数 abn が与えられます。a の末尾に1桁ずつ数字を追加していき、毎回の追加後にその数が b で割り切れるようにすることが求められます。

  • 数字を1桁追加した直後、ab で割り切れるようにします。

  • この操作を n 回繰り返したとき、あり得る最小の a の値を出力します。

  • 条件を満たすことができない場合は fail を出力します。

なお、1桁追加するごとに必ず割り切れているかどうかを確認する必要があります。

入出力例

入力:

a=5 b=4 n=4

出力:

52000

解説

まず、追加する最初の1桁として 0〜9 の数字を順番に試します。どの数字を追加しても ab で割り切れない場合、答えは -1 となり、これは n 桁を追加しても a が決して b で割り切れないことを意味します。

一方、条件を満たす数字が存在する場合は、その中で最も小さい数字を採用し、残りの (n-1) 桁にはすべて 0 を追加します。ある数が b で割り切れるならば、a×10a×100…も同様に b で割り切れるためです。この貪欲な戦略によって、常に最小の答えが得られます。

C++ 実装例

#include <iostream>
using namespace std;

int main() {
    int a = 5, b = 4, n = 4;
    int num = a;

    // 追加する最初の1桁を0〜9の中から探索
    for (int i = 0; i <= 9; i++) {
        int temp = a * 10 + i;
        if (temp % b == 0) {
            a = temp;
            break;
        }
    }

    // 条件を満たす桁が見つからなかった場合
    if (num == a) {
        a = -1;
    }

    // 残りの(n-1)桁はすべて0を追加
    for (int j = 0; j < n - 1; j++) {
        a *= 10;
    }

    if (a > -1) {
        cout << a;
    } else {
        cout << \"fail\";
    }
    return 0;
}

計算量と注意点

最初の1桁の探索は最大でも10回の試行で済むため、全体の計算量は O(1) と非常に効率的です。ただし、桁を追加するたびに a は急速に大きくなるため、int 型ではオーバーフローする恐れがあります。大きな入力に対応する場合は、文字列として処理するか、long long 型や多倍長整数を利用することをおすすめします。

  1. 各部分文字列が回文になるように文字列を分割する方法をすべて求めるC++プログラム

    本記事では、与えられた文字列を「すべての部分文字列が回文(前から読んでも後ろから読んでも同じになる文字列)」となるように分割する方法をすべて列挙するC++プログラムを紹介します。たとえば「tutorials」という文字列なら、1文字ずつに分割する方法や、先頭の「tut」をひとまとまりにして残りを1文字ずつにする方法などが該当します。 アルゴリズム 処理の基本的な流れは次のとおりです。 Begin 文字列を入力として受け取る。 関数 partitionadd(vector<vector<string>> &u, string &s, vec

  2. PythonでAの倍数かつ桁の合計がBと等しい最小の正の整数を求める方法

    問題の概要 2つの整数 A と B が与えられたとき、「A で割り切れ、かつ各桁の数字の合計が B と等しい」という条件を満たす最小の正の整数 M を求めます。そのような数が存在しない場合は -1 を返します。 例えば、入力が A = 50、B = 2 の場合、出力は 200 となります。200 は 50 で割り切れ、桁の合計も 2 + 0 + 0 = 2 となり、両方の条件を満たす最小の数だからです。 解法のアプローチ:幅優先探索(BFS) この問題は幅優先探索(BFS)を用いることで効率的に解けます。BFS は桁数の少ない数から順に探索を進めるため、最初に見つかった解が必ず最小値になりま