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

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

新規登録して質問してみよう
ただいま回答率
85.35%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

1回答

1012閲覧

組み合わせと剰余算について

akira-

総合スコア2

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

0クリップ

投稿2020/10/11 10:53

編集2020/10/11 11:51

初学者です。先生からいただいた問題です。
組み合わせの計算をし、その値を100で割ったときの余りを出すプログラムを作りたいのですが、再帰を使うって入力値を大きくすると、再帰処理の回数が非常に大きくなってしまうのとてつもなく遅くなってしまいます。
またループ処理を使ってみても、調べてみたらオーバーフロー?を起こしてしまいマイナスの値※が出たり、0がでたりしてしまいます。
剰余算をしながら?計算をすると値がオーバーフローを起こさずに表現できると思うのですが,(ex (a+b)% d = a%d + b%dのような感じ)いまいちコードへの表現の仕方わかりません。どのように工夫する必要があるのかご回答いただけたら幸いです。


./a.out
123123 12332
-1

c

1#include <stdio.h> 2 3int com(int n, int k){ 4 5 if(k==0 || k==n){ 6 return (1); 7 }else if (k==1){ 8 return (n); 9 }else{ 10 return (com(n-1, k-1) + com(n-1, k)); 11 } 12} 13 14 15 16int main(void){ 17 int n, k; 18 19 scanf("%d %d", &n, &k); 20 printf("%d\n", com(n, k)%100); 21 22 return 0; 23 24}

c

1#include <stdio.h> 2 3int combi(int n, int r) 4{ 5 int i; 6 int k=1; 7 8 for(i=1; i<=r; i++){ 9 k = k*(n-i+1)/i; 10 } 11 12 return k; 13} 14int main() 15{ 16 int n, r; 17 scanf("%d %d", &n, &r); 18 19 printf("%d\n", combi(n, r)%100); 20} 21

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

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

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

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

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

mjk

2020/10/11 11:18

何の練習問題かを明記した方が良いと思います。 見てる人にはそれが何の練習問題なのか分かりません。 学校の宿題なのか、友達に出された問題なのか、オンライン上の問題なのか、著書の問題なのか・・・
mjk

2020/10/11 11:24

>>先生からいただいた問題です。 先生に聞きましょう。
mjk

2020/10/11 11:27

https://teratail.com/help/avoid-asking 推奨していない質問 学校の課題を解いてほしい等の質問は、具体的にプログラミングで困っている質問ではないと考え、推奨していません。
akira-

2020/10/11 11:53

学校の課題というより先生からいただいた大量の練習問題のうちの1つです。先生にはヒントはいただきましたが、ここまでが限界でした。
Bull

2020/10/11 12:16 編集

練習問題ということなのでヒントだけですが、「剰余を求めながら計算する」という考え方は間違っていないです。 ただし、途中に除算が入ると正しく答えが求まらないです。 加算だけで組み合わせの数を求める方法を考える必要があります。 最初のソースコードはおそらく、答えが求まるような気がします。 しかし、質問にも書かれている通り再帰呼び出しが、かなり深くなるので時間がかかりますね。
mjk

2020/10/11 12:15

もしかすれば回答つくかもしれませんが・・・ 長い目で見た場合に本人の為にならないという考え方があるのか、テラテイルでは課題の質問には回答がつきにくかったり、そういう質問に回答すると低評価されたりする慣習?のようなものがあるのかもしれません。 いきなり低評価されて驚かれないように質問する時は気をつけた方が良いと思いました。 (テラテイルを利用するのに慣れているようなので余計なお節介だったかもしれませんね)
akira-

2020/10/11 12:33

みなさまありがとうございました。すこし時間をかけて考えてみます。
guest

回答1

0

ベストアンサー

パスカルの三角形を利用しましょう。

C(0,0) = 1
C(1,0) = 1, C(1,1) = 1
C(2,0) = 1, C(2,1) = 2, C(2,2) = 1
C(3,0) = 1, C(3,1) = 3, C(3,2) = 3, C(3,3) = 1

C(n,k) = (C(n-1, k-1) + C(n-1,k)) % 100 を使って、
C(123123,0), C(123123,1), ... まで求めます。

2次元配列は要りません。
static int c[1000000] = { 1 }; を用意し、
n が 1 の時、c[1] = 1
n が 2 の時、c[2] = 1, c[1] = (c[0] + c[1]) % 100
n が 3 の時、c[3] = 1, c[2] = (c[1] + c[2]) % 100, c[1] = (c[0] + c[1]) % 100

投稿2020/10/11 12:37

編集2020/10/11 13:08
kazuma-s

総合スコア8224

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

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

akira-

2020/10/11 14:58

#include <stdio.h> static int c[1000000] = {1}; int main(void){ int n, r, i, j, l; scanf("%d %d", &n, &r); for(l=1; l<=n; l++){ c[l]=1; } for(i=1; i<=n; i++){ for(j=i-1; j>0; j--){ c[j] = (c[j-1] + c[j]) % 100; } } printf("%d\n", c[r]); return 0; } コード書くことができました。ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問