#include<stdio.h>

int main()
{
int n;
int m;
int i;
int kumi;
int san;

printf("n:");
scanf("%d",&n);
printf("m:");
scanf("%d",&m);

for(kumi=1,i=n;i>n-m+1;i--){
kumi=kumi*i;
}
for(san=1,i=1;i<=m;i++){
san=san*i;

}


printf("%d個の中から%d個を取り出す組み合わせは%dとおり\n",n,m,kumi/san);

return 0;
}

組合わせの値がおかしいです。

A 回答 (3件)

2箇所気になる点があります。



1.最初のforループ
i=n~n-m+1までのm個についてこのループを実行するためには
for(i=n;i>n-m;i--)
でないといけません。tomo_ko_nさんのコードだと、i=n-m+1の場合はループが実行されません。

2.オーバーフローへの対処
nやmをある程度の数にすると簡単にオーバーフローします。
そのチェックはしておいたほうが良いでしょう。
#1にあるように掛け算と割り算を同じループ内で実行するとオーバーフローを起こしにくくなります。
また、m>n/2の場合は、m=n-mとしてから計算するとより速く計算できます。
    • good
    • 0
この回答へのお礼

わかりやすくてありがとうございました。

お礼日時:2009/05/28 19:37

「おかしい」とは「何がどのようにおかしい」のでしょうか?


具体的な例で, 「このような入力に対してこう期待されるのにこんなのが出てきた」と書いてみてください.
#1 は超能力者か?

この回答への補足

取り出す組み合わせは%dとおりの所です。
例えばn=5、m=3だと、10になるはずなのになりません。

補足日時:2009/05/28 19:32
    • good
    • 0

#include <stdio.h>



int main(void)
{
int combi, n, m, t, i;

do {
printf("n:"), scanf("%d", &n);
printf("m:"), scanf("%d", &m);
} while (n < m || m < 0);

for (combi = i = 1, t = n; i <= m; n--, i++) {
combi *= n;
combi /= i;
}
printf("%d個の中から%d個を取り出す組み合わせは%dとおり\n", t, m, combi);
return 0;
}
    • good
    • 0
この回答へのお礼

参考になるプログラムありがとうございました。

お礼日時:2009/05/28 19:35

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Q異なるn個の整数からr個の整数を取り出す組み合わせ

異なるn個の整数からr個の整数を取り出す組み合わせの数
nCrを求める関数
int combination(int n, int r){ /* ・・・ */}
を作成せよ。なおnCrは以下のように定義される。

nCr = n-1Cr-1 + n-1Cr (ただし nC0 = nCn =1、nC1 =n )

(新版 明解C言語 入門編(柴田望洋 著) P.197 演習8-6)

というので答えが

int combination(int n, int r)
{

if((n>r) && (r>0)){
return combination(n-1,r-1) + combination(n-1,r);
}
else if(n==r || r==0){

return 1;
}
}

・という風になると教えてもらったのですがなぜこうなるのかが分かりません。
・else if(n==r || r==0){ というのは削っても正常に動きますが、必要な物なのでしょうか?

・またifを使うときは
if→eise if →else の順に使って
2つの時は if→else と使っていたのですが
上のものはif→else ifと書いています。
加えてelse(n==r || r==0){ と書いたらコンパイルエラーになってしまいました
なぜelse ifと書くのでしょうか?

以上3点について教えてください。よろしくお願いいたします。

異なるn個の整数からr個の整数を取り出す組み合わせの数
nCrを求める関数
int combination(int n, int r){ /* ・・・ */}
を作成せよ。なおnCrは以下のように定義される。

nCr = n-1Cr-1 + n-1Cr (ただし nC0 = nCn =1、nC1 =n )

(新版 明解C言語 入門編(柴田望洋 著) P.197 演習8-6)

というので答えが

int combination(int n, int r)
{

if((n>r) && (r>0)){
return combination(n-1,r-1) + combination(n-1,r);
}
else if(n==r || r==0){

return 1;
}
}

・とい...続きを読む

Aベストアンサー

>・という風になると教えてもらったのですがなぜこうなるのかが分かりません。

もしかすると、再帰呼び出しという概念がわかっていませんか?
再帰呼び出しというのは、関数がその処理の中で自己の呼び出しを行なう事です。

ところで、
nCr = n-1Cr-1 + n-1Cr (ただし nC0 = nCn =1、nC1 =n ) ・・定義A
と定義されるということは
右辺式の、n-1Cr-1 と n-1Crを求めるのに定義Aを用なければならないという事です。
そのため、n-1Cr-1 と n-1Crを求める右辺式にもxCyがでてきます。
これが、r=0でnC0か、n=rでnCnになって固定値(=1)になるまで、続きます。

ソースプログラムを見ると、
int combination(int n, int r)
{
  if((n>r) && (r>0)){
    return combination(n-1,r-1) + combination(n-1,r);  /* ※ */
  }
  else if(n==r || r==0){
    return 1;
  }
}

1)combination関数は、パラメータnとrからnCrを求める関数である。
2)nCrを求めるためには、n-1Cr-1とn-1Crを求める必要がある。
 この二つを求めるために、※の箇所でcombination関数自体をを呼び出している。
3)※で呼び足された二つのcombination関数はそれぞれのパラメータに従い、
 また、combination関数を呼び出す。
4)3)の呼び出しの繰返しは、combination(n-1,r)のr以外は1づつ減っていくので
 (n>r) && (r>0)が成立しないところまで継続する。
 (n>r) && (r>0)が成立しないところまで達すると、combination関数は1を返し
 その結果を持って、3)の呼び出し関係を遡って最初のcombination関数の呼び出し
 まで返って答えをだす。

という事です。

>・else if(n==r || r==0){ というのは削っても正常に動きますが、
>必要な物なのでしょうか?

else if(n==r || r==0){ を削るというのは

  else if(n==r || r==0){
    return 1;
  }

全体をを削ってますか、それとも

  else {
    return 1;
  }

と条件だけを削ってますか?

後者であればこの例題については問題ないと思います。

それは、elseだけにすると、(n>r) && (r>0) の成立しない(条件が逆)時に、else節に
入ります。
else節に入る時は、(n>r) && (r>0) が成立しない時 = (n<=r) || (r<=0) の時なので
削った条件 (n==r || r==0) を含んでいるからです。

前者であると、(n>r) && (r>0)が成立しなくなった時、combination関数の呼び出しは
止まり、返す値が不定になり、なにが返るかわかりません。その結果計算結果がおかしく
なると思います。
(コンパイラの仕様としてなにか固定値を返すコードを生成していればその値に従った
 計算結果になります。)

>・またifを使うときは
>if→eise if →else の順に使って
>2つの時は if→else と使っていたのですが
>上のものはif→else ifと書いています。
>加えてelse(n==r || r==0){ と書いたらコンパイルエラーになってしまいました
>なぜelse ifと書くのでしょうか?

これは、C言語の文法がそういうもの「elseにはif無しに条件は書けない」からとしか
お答えできません。

>・という風になると教えてもらったのですがなぜこうなるのかが分かりません。

もしかすると、再帰呼び出しという概念がわかっていませんか?
再帰呼び出しというのは、関数がその処理の中で自己の呼び出しを行なう事です。

ところで、
nCr = n-1Cr-1 + n-1Cr (ただし nC0 = nCn =1、nC1 =n ) ・・定義A
と定義されるということは
右辺式の、n-1Cr-1 と n-1Crを求めるのに定義Aを用なければならないという事です。
そのため、n-1Cr-1 と n-1Crを求める右辺式にもxCyがでてきます。
これが、r=0でnC...続きを読む


人気Q&Aランキング

おすすめ情報