質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

Q&A

解決済

3回答

561閲覧

10^k (mod M)の値を保持した配列を高速で求めたい

pifacela

総合スコア19

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

0グッド

0クリップ

投稿2019/12/31 18:24

編集2019/12/31 18:28

実現したいこと

10^k (mod M)の値を保持した配列を高速で求めたい

考えたこと

  • 10^k = 10^(k-1) * 10
  • 10^(k-1) * 10 (mod M) ≡ (10^(k-1) (mod M)) * (10 (mod M)) (mod M)

上式を使ってk=0から求めていける

C++

1const int MAX_DIGIT = 100; // 桁数の上限 2vector<int> a(MAX_DIGIT); // 10^k (mod M)の値を保持する配列 3a[0] = 1; 4for (int k = 1; k < MAX_DIGIT; k++) { 5 a[k] = a[k-1] * 10; 6 a[k] %= M; // 10^k (mod M) 7}

発生している問題

先ほどのコードで構築した配列aと実際の答えが異なる

具体的には...

(long long int)pow(10, k) % Mが10^k (mod M)の値

C++

1for (int k = 0; k < 15; k++) { // 試験的にとりあえずk=0...14をやる 2 cout << (a[k] == (long long int)pow(10, k) % M) << endl; 3}

この出力が全て1と出るはずなのだが、そうはならなかった


この原因が分かる方がいらっしゃいましたら、ご回答をお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

ついこの間も同じような問題を見かけたのですが、powの返り値はdouble型なので大きな値を入れた場合に、たとえそれが整数演算であっても浮動小数点誤差が発生します。
powを使うのはやめましょう。

ついでですが、10^kを計算するときにkを半分に割って行った方が計算は速いでしょう。
端数は上手いことやってください。

投稿2019/12/31 18:50

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

pifacela

2019/12/31 19:02

ご回答ありがとうございます。 これにはまって、3時間くらい溶かしてました。 大人しく、その方法で実装してたものを使います。。。
退会済みユーザー

退会済みユーザー

2019/12/31 19:07 編集

なまじ整数の計算だから結構引っかかってしまうようで... doubleの精度は2進数53桁、10進数換算で15桁強だそうです(10^kならk=16から誤差が出るはず)
pifacela

2019/12/31 19:16

ありがとうございます。 これでやっと寝れる...!
guest

0

こちら側の確認不足でした。
おおよその原因はわかりました。ただ、詳細は分かりかねますが。。。

std::powは浮動小数点の型(float,double,long doubleとか)で値を返すようです。
コードでは、それをlong long int、つまり整数型にキャストしました。
そのキャスト時に、ビットの関係で値に誤差が出たと思われます。(あってるのかなぁ。。。)

投稿2019/12/31 18:57

pifacela

総合スコア19

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ごめんなさい、kは15未満でした…

誤った回答

桁あふれしているということはないですか?
long long intは64ビットのため、19桁程度が限界です。
20桁以上、つまりkが19以上だと桁あふれし、マイナスの値になっているなどにより、その後の剰余算が正しく計算されていない可能性があります。

投稿2019/12/31 18:33

編集2019/12/31 18:34
swordone

総合スコア20651

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

pifacela

2019/12/31 18:46

こちら側の確認不足でした。 おおよその原因はわかりました。ただ、詳細は分かりかねますが。。。 pow(10, k)がバグっているようです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問