• ベストアンサー

組合せ

php504の回答

  • ベストアンサー
  • php504
  • ベストアンサー率42% (926/2160)
回答No.3

combination関数を使わずといのは再帰関数を使わないでということでしょうか n!か(m - n)!の大きい方で約分する関数を作りました /* mCn を計算する関数 */ int combi(int m, int n) { int i, numerator, denominator; if (m < n || n <= 0 || m <= 0) { return 0; } numerator = 1; denominator = 1; if (m > n / 2) { // 分子 n!部分は計算しない for (i = m; i >= (n + 1); i--) { numerator *= i; } // 分母 (m - n)!のみ計算 for (i = m - n; i > 0; i--) { denominator *= i; } } else { // 分子 (m - n)!部分は計算しない for (i = m; i >= (m - n + 1); i--) { numerator *= i; } // 分母 n!のみ計算 for (i = n; i > 0; i--) { denominator *= i; } } return (numerator / denominator); }

juck0808
質問者

お礼

回答ありがとうございます。 丁寧なアドバイス、ありがとうございます。 参考にさせて頂きます!

関連するQ&A

  • 組み合わせ プログラミング

    c言語についてです os linux コンパイラはgccです long fact2(int n,int m)を作成してfact2(n,m)を使って組み合わせを計算するプログラムを作れという問題で下記のように作りましたが コンパイルできません. エラーメッセージは 2-1.c:14: error: 関数 `fact2' への引数が少なすぎます 2-1.c:14: error: 関数 `fact2' への引数が少なすぎます 2-1.c:14: error: 関数 `fact2' への引数が少なすぎます です 関数のとこが違うと思うですが どうしたらいいのかわかりません それともなにか他のとこが違うのでしょうか? #include <stdio.h> long fact2(int,int); main() { int n, m; long c; printf(" nCm (n>m) \n"); printf("input n m ="); scanf("%d %d",&n, &m); c =fact2(n) / (fact2(m) * fact2(n-m)); printf("%dC%d = %ld\n",n,m,c); } long fact2(int n,int m) { int i; long c=1; for(i=1; i<=n; i++) c*=i; return(c); }

  • 困ってます…nCrを求めるC言語プログラミング

    nCr、つまりn個のうちr個を取り出すときの場合の数を求めるプログラミングを作りたいのですが、どうもうまくいきません。 関数combinationを作って求めるという指定もあり、自分で出来るとこまで作ってみたのですが訳がわからなくなってしまい、かなり困っています…; コンパイルは出来るのですが実行してもセグメントエラーが出るばかりで… すみませんがご指摘していただけないでしょうか…? #include<stdio.h> //階乗を計算する関数 int fact(int num){ int i; if(num < 0){ return -1; } else if(num == 0){ return 1; } else if(num == 1){ return 1; } else { i = num * fact(num - 1); return i; } } //コンビネーションを計算 int combination(int n, int r) { int fact(int num); int i; i=fact(n)/fact(r)/fact(n-r); return combination(n-1, r-1)-combination(n,r-1); } int main(void) { int n, r; while ( printf("n r を入力して下さい。"), scanf("%d%d", &n, &r) == 2 ) { printf("nCr(%d,%d)=%d\n", n, r, combination(n, r)); } return 0; }

  • 桁落ちのプログラムで真の値と計算結果

    #include <stdio.h> const double PI=3.141592653589793; double sum(long m) { double n,term,sum; n=1; sum=0; term= 1.0/ (n*n);/*初項*/ while( n<=m ){ sum+=term; n++; term= 1.0/ (n*n);/*次項の計算*/ } return sum; } /*この計算の答えはπ*/ int main(void) { double s; long m; int i; m=1; for(i=0;i<9;i++){ s=sum(m); printf("%2d m=%10ld sum= %22.16e err= %22.16e \n",i,m,s,s-PI*PI/6); m*=10;/*次は10倍にする*/ } return 0; で真の値と計算結果を調べるにはどうしたらいいのでしょうか?

  • 桁落ちの誤差について

    #include <stdio.h> const double PI=3.141592653589793; double sum(long m) { double n,term,sum; n=1; sum=0; term= 1.0/ (n*n);/*初項*/ while( n<=m ){ sum+=term; n++; term= 1.0/ (n*n);/*次項の計算*/ } return sum; } /*この計算の答えはπ*/ int main(void) { double s; long m; int i; m=1; for(i=0;i<9;i++){ s=sum(m); printf("%2d m=%10ld sum= %22.16e err= %22.16e \n",i,m,s,s-PI*PI/6); m*=10;/*次は10倍にする*/ } return 0; のプログラムで誤差が生じる理由ってなんなんでしょうか?

  • 組み合わせ

    n個の集合からp個を取る組み合わせの総数を出力するプログラムなんですが nCp=n!/p!(n-p)!という式を使い #include<stdio.h> int kaijo(int m); int comb(int n,int p); int main(void) { int i,j; printf("n="); scanf("%d",&i); printf("p="); scanf("%d",&j); printf("comb(%d,%d)=%d\n",i,j,comb(i,j)); } int kaijo(int m) { if(m>0) return(m*kaijo(m-1)); else return 1; } int comb(int n,int p) { if(n>0) return((n*kaijo(n-1))/(p*kaijo(p-1)*(n-p)*kaijo(n-p-1))); else return 1; } と書いてみたのですがこれではnが大きいとC言語のint型で扱える最大値を超えてしまい正しい結果が出力されません。  そこでint型を使ったままでnやpが大きい場合でもある程度出力できるようにしたいのですがどう改良したらよいのでしょうか? おそらくnCp=n*(n-1)*・・・*(n-p+1)/p!という式を使うのですがよく分かりません。よろしくお願いします。

  • C#でmCnの求め方について 階乗、組み合わせ

    C#の勉強を始めて数日の初心者です。 8個の中から4個を選ぶ組み合わせ 式1      m! mCn = ――――     n!(m -n)! 式2    m×(m-1)×(m-2)×…×(n+1) mCn = ――――――――――――       (m-n)! ---------------------------------------------- 勉強している本の中で、VBSctiptで式2を下記のような 記述例がありましたが、これをC#で書き換えると どのようになりますか? VBScriptの内容は全然分かりません。 メソッドの再帰呼び出し等は使わず、 あくまで、For文のみを使ってC#で記述したいです。 m = CInt(InputBox("何個の中から?")) n = CInt(InputBox("何個を選びますか?")) C = 1 For i = m To (n + 1) Step -1 c = c * i Next For i = (m - n) To 1 Step -1 c = c / i Next MsgBox "組み合わせ = " & CStr(c) ---------------------------------------------- 8個の中から4個を選ぶ組み合わせ 自分で書いてみたのですが、上記の式2のVBScriptの例に のっとった記述方法ではない感じがします。 int m = 8; int n = 4; int c = 0; for (int i = 1; i <= m; i++) { c = c * m; // mの階乗を求める } for (int i = 1; i <= n; i++) { d = d * n; // nの階乗を求める } e = d * d; // これの意味がよく分かりません。 f = c / e; Console.WriteLine(f); // 70 よろしくお願いします。

  • ランダウ量子力学 第二量子化(ボーズ粒子の場合)

    小教程を読んでいるのですが… ボソンの系のN個粒子の波動関数 Ψ=(N_1!…/N!)^(1/2)ΣΨ_p1(ξ1)Ψ_p2(ξ2)…Ψ_pN(ξN) について、 f^(1)_a をa番目の粒子に関する物理量演算子とした上で、全ての粒子について対称な演算子F^(1)=Σf^(1)_a の行列要素の求め方がまったく載っていません。 <N_i, N_k-1 | F | N_i-1, N_k>=f _ik√NiNk として答えが載っていますが、 Ψ_1=(N_1!…N_i-1!/N!)^(1/2)ΣΨ_p1(ξ1)Ψ_p2(ξ2)…Ψ_pN(ξN) Ψ_2=(N_1!…N_k-1!/N!)^(1/2)ΣΨ_p1(ξ1)Ψ_p2(ξ2)…Ψ_pN(ξN) として ∫Ψ*_1FΨ_2 dξ を計算すればよいのでしょうか?? それでも、とても簡単とはいかなさそうなのですが… 指針やアドバイスだけで構わないので、どなたかご教授お願いできますか。 よろしくお願いします。

  • 組み合わせ順列

    nCrを求める関数combination(n,r)をC言語で作りたいのですが、どうすればよいか教えてください。また、参考となるようなサイトを教えてください。僕の作った関数だと、すぐに桁あふれになってしまいます。そのことを考慮して、桁あふれにになりにくい関数もつくりました。これは パスカルの三角形の関係を使ったnCr=n-1Cr +n-1Cr-1の関係を使っての再帰関数です。しかし、これだと結果を出すのに時間がかかってしまいます。僕がつくった関数をいくつか出しておきますのでいい考えがあれば教えてください。64C32が高速に正確に出れれば最高です。 long combination(int n,int r) { int i, a, b; long c; if(r>n/2) r=n-r; a= n; b= 1; c= 1L; for(i=0 ;i< r ;i++){ c= c* a/ b; a--; b++; } return c; } これはすぐに桁あふれになってしまう。 long combination(int n,int r) { int i, a, b; double c; if(r>n/2) r=n-r; a= n; b= 1; c= 1.0; for(i=0 ;i< r ;i++){ c= c/b*a; a--; b++; } return (long)c; } これはcをdoubleにして計算する分、丸めこみが生じ誤差がでる。 long combination(int n,int r) { long c; if(r> n-r) r=n-r; if(r==0) return 1; else if(r==1) return n; else{ c= combination(n-1,r-1)+ combination(n-1,r); return c; } } これは誤差は出ず正確であるがいかんせん遅い!

  • 桁あふれ誤差のプログラムで質問です。

    1から15までの階乗を計算するプログラムで、階乗を求める関数を定義してその結果を確認し、その際に階乗の計算を開始する数と終了する数を記号定数で定義(#defineを使って)したいのですが、分からなくて困っています。 関数を使わないで以下のようにやり、 #include <stdio.h> #include <math.h> int main(void) { int n; int ans=1; for(n=1;n<=15;n++) { ans=ans*n; printf("%d!=%d\n",n,ans); } return 0; } これをやってみてなんとか結果が確認できたのですが、上記のように、階乗を求める関数を定義して、この上記のプログラムを書き換えて、そのときに階乗の計算を開始する数と終了する数を記号定数で定義(#defineを使って)して行いたいのですが、 分からなくて本当に困っています。助けてください。

  • 次のプログラムが作れません…

    キーボードから与えられた整数iに対して、iの階乗(i!)を求める関数"fact"を作成するというものなのですが… メイン関数は次のように与えられています。 #include<stdio.h> int fact(int); int main(void){ int in, i; printf("Input a number:"); scanf("%d",&in); for (i=1; i<=in; i++){ printf(" %d %d\n",i , fact(i) ); } return 0; } よろしくお願いします。