• ベストアンサー

約数のプログラミングです

 nが与えられたとき、その正の約数をすべて求めるプログラムを書け。   これは擬似言語でも、Basicでもいいそうです。  初心者なのでわかりません。宜しくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.1

C言語で、単純に void main( int ac, char* av[] ) { int i,m,n; if( ac != 2 ) return; m = atoi( av[1] ); /* 数字を取得 */ if( m < 0 ) n = -1 * m; /* 負の場合 */ else n = m; /* 正の場合 */ for( i=1; i<n; i++ ){ if( n % i == 0 ){ /* 余りが0の場合iはnの約数 */ printf("%d\n", i); } } } これで、正の約数はすべて得られるが、nが十分大きい場合結果が出るまでに時間がかかり、負荷が高いのでちょっと問題です。 多分、間違いなくもっと良い回答例があるとは思いますが、一例ということでこれでどうでしょうか。

goosasuke
質問者

お礼

ありがとうございました。助かります。

その他の回答 (3)

  • TAGOSAKU7
  • ベストアンサー率65% (276/422)
回答No.4

以下に処理の流れとプログラムを記します。プログラムと照らし合わせて読んでください。 約数とは、「因数を掛け合わせたもの」ですよね? だからまず因数を求める関数を作成しました。(関数:subFactorization) そのとき注意すべきは 10の因数を求めるのには5まで、7の因数を求めるには4までに因数がないときはそれ以上の値に因数は存在しないという点です。なので途中でそのリミットになったら抜ける条件を追加しました。(変数:lngRimitがそれにあたります。) 次にその因数を掛け合わすために、その因数を順順に取り出す関数を作成しました。(関数:subMultiplyMatrix) 実際に例をあげると最初に210を因数分解した場合 3,5,7という値が得られます。これらを掛け合わせるとき 3 5 7 3×5 3×7 5×7 3×5×7 という7パターンがあります。 この7パターンの値を配列に収めるようなループが必要でした。(プログラム中のi,jを使用してループしてるのがその部分です) 次にその配列内の値を乗算する関数を作成しました。(関数:subMultiplyMatrix) しかし、これだけではだめでした。 210だから因数は[3,5,7]だけど、12のときは[2,2,3]という値を得ます。この条件でできるパターンは 2 2 3 2×2 2×3 2×2 2×2×3 となり、重複する値が返ってきます。これではこまります。 なので答えを収める変数をコレクションで宣言し、値のセットをするときに"KEY"という文字列と値を組み合わせたKEYを同時にセットし、重複した値を記憶しないようにしました。(KEY & wkLng となってる部分です。) ちなみにOn Error Resume Next というのが書いてありますが、これがないと、「重複したキーが存在する」というエラーが生じます。 あとは単なるメッセージボックスに出力をしてるだけです。環境を特に書いてなかったので、Join関数を使用してます。VB6限定ですが、大丈夫かな? 以上が処理の流れです。 いやーホント勉強になりました。 以下のソースを貼り付けて見てください。 Option Explicit Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" ( _   Destination As Any, _   Source As Any, _   ByVal Length As Long _ ) Private lngAry()  As Long '因数記憶用の配列 Private lngCnt   As Long '因数のカウンタ Sub Main()   Dim lngDef     As Long '初期値   Dim ansCollection  As Collection  '答えの入るコレクション      Dim i    As Long      '初期値を得る   On Error GoTo PGMERR   lngDef = InputBox("", "初期値を入力してください")   On Error GoTo 0      '初期値が1未満をエラーとします   If lngDef < 1 Then GoTo PGMERR      '因数カウンタの初期化   lngCnt = 0   '因数記憶用の配列を初期化   Erase lngAry         '因数分解をする   Call subFactorization(lngDef)         'コレクションを初期化   Set ansCollection = New Collection   'とりあえず1を追加   ansCollection.Add 1, "KEY1"   '配列の中身を順に掛け合わせ、コレクションに追加する   Call subMultiplyMatrix(lngAry, ansCollection)         '答えの出力   Call ansOut(ansCollection)    PGMEND:   Exit Sub PGMERR:   Call MsgBox("初期値に不正な値が入力されました") End Sub '因数分解 Sub subFactorization(inLng As Long)   Dim i      As Long   Dim lngRimit  As Long      '中間の値を求める(切り上げ)   lngRimit = Int((inLng / 2 * 10 + 9) / 10)      For i = 2 To inLng     '割ってあまり0のとき、因数とする     If (inLng Mod i) = 0 Then       '因数を記憶       ReDim Preserve lngAry(lngCnt) As Long       lngAry(lngCnt) = i       '因数のカウンタを増やす       lngCnt = lngCnt + 1       '因数で割った値でさらに因数分解       Call subFactorization((inLng / i))       Exit For     End If          '中間の値になっても因数が見つからないとき、引数自身が因数とする     If i >= lngRimit Then       '因数を記憶       ReDim Preserve lngAry(lngCnt) As Long       lngAry(lngCnt) = inLng       '因数のカウンタを増やす       lngCnt = lngCnt + 1       Exit For     End If   Next i End Sub '掛け算マトリックス Sub subMultiplyMatrix(inlngAry() As Long, inColection As Collection)   Dim wklngAry() As Long      Dim i    As Long   Dim j    As Long   Dim wkLng  As Long      '因数に同じ値が存在するときに発生するエラーを無視させる   On Error Resume Next   For i = 0 To lngCnt - 1     For j = 0 To (lngCnt - 1) - i       Call copyAry(wklngAry, inlngAry(j), i + 1)       wkLng = subMultiply(wklngAry)       inColection.Add wkLng, "KEY" & wkLng     Next j   Next i   On Error GoTo 0 End Sub '配列の中身を掛け算して値を返す関数 Function subMultiply(inlngAry() As Long)   Dim i    As Long      subMultiply = inlngAry(0)   For i = LBound(inlngAry) + 1 To UBound(inlngAry)     subMultiply = subMultiply * inlngAry(i)   Next i End Function '配列の中身をエリアの分だけコピーする関数 Sub copyAry(inDest() As Long, inSrc As Long, inArea As Long)   ReDim inDest(inArea - 1) As Long   Call CopyMemory(inDest(0), ByVal VarPtr(inSrc), ByVal LenB(inSrc) * inArea) End Sub '答えの出力 Sub ansOut(inCollection As Collection)   Dim wkStr    As String   Dim ansCount  As Long   Dim wkStrAry() As String   Dim i      As Long      ansCount = inCollection.Count      ReDim wkStrAry(ansCount - 1) As String      For i = 1 To ansCount     wkStrAry(i - 1) = inCollection.Item(i)   Next i      wkStr = "答えは[" & Join(wkStrAry, ",") & "]です"   MsgBox wkStr End Sub

  • arika
  • ベストアンサー率9% (18/186)
回答No.3

回答がでてるんで、よろしいかと思いますが、 ループは与えられた数のルートをとったものまでで よいはずです。 そのためには、あまりが0となったときの商も 約数とすればよいかと思います。

goosasuke
質問者

お礼

ありがとうございました。参考にいたします。

  • ranx
  • ベストアンサー率24% (357/1463)
回答No.2

最近ツッコミ専門になりかけている...。 yusuke5111さんのやり方が最も簡単ですね。 ただし、n自体もnの約数なので for( i=1; i<=n; i++ ){ とすべきですね。

goosasuke
質問者

お礼

勉強になります。ありがとうございます。

関連するQ&A

  • 約数について

    nは自然数でnの約数を小さい方から順に一から並べると 6番目が8で、8番目が14になるという。このようなnのうち最小のものを求めよ。 という問題があってわからなかったんで答え見たんですけど 56の約数にない356のいずれかがnの約数になることがわかるのですか? わかりやすく教えていただくと幸いです…

  • 約数

    自然数Nの約数の総和が60であるものをすべてもとめよ。 答えは(おそらく)24,38,59です。(しらみつぶしに探した結果) どのように探したら効率いいでしょうか?

  • 約数の個数

    私が今使っている参考書の数Aのテーマの一つで「約数の個数」というものがあり、解説として  自然数Nの素因数分解が   N=p^a*q^b*r^c(←pのa乗×qのb乗×rのc乗) であれば、Nの正の約数の個数は    (a+1)(b+1)(c+1)個である この公式の補足説明の中に、  ここでは、正の約数の個数だから上の数となったが、「Nの約数となる整数」というときには、負の約数も考える必要があるから、さらに上の数の2倍で、2(a+1)(b+1)(c+1)である という解説がでていました。  負の約数 という概念がわかりません。どういうもなのでしょうか。よろしくお願いします。 なお、この参考書は、受験用の公式集です。

  • 約数

    与えられた自然数N=(p^l)*(q^m) □で、l,mは0以上の整数について (1)Nの正の約数の個数 (2)Nの正の約数の総和 (1)上記の問題の(1)のNの正の約数の個数が(l+m+1)(l+1)(m+1)となるように□に適する条件を書く問題で 回答はp,Qの最大公約数をrとするとp/r,q/r,rは異なる素数らしいのですがどうしてrを割るのですか? 例えば2つの整数aとbの最大公約数をGとくと、a=a'G,b=b'Gとおける a'とb'は素とするとこうな考えをするのでしょうか? (2)(1)の条件のもとで、(2)を解くと p/r=a,q/r=bとおくと N={(ar)^l}*{br}^m =(a^l)*(b^m)*r^(l+m) Nの正の約数の総和は S=((a^0)+(a^1)+…(a^l)) ((b^0)+(b^1)+…(a^m)) ((r^0)+(r^l)+…(r^(l+m))) から {1-a^(l+1)}/1-a * {1-b^(m+1)}/1-b *{1-r^(l+m+1)}/1-r になることわ分かりません。

  • 最大約数

    与えられた自然数N=(p^l)*(q^m) □で、l,mは0以上の整数について (1)Nの正の約数の個数 (2)Nの正の約数の総和 (1)上記の問題の(1)のNの正の約数の個数が(l+m+1)(l+1)(m+1)となるように□に適する条件を書く問題で 回答はp,Qの最大公約数をrとするとp/r,q/r,rは異なる素数らしいのですがどうしてrを割るのですか? (2)(1)の条件のもとで、(2)を解くと p/r=a,q/r=bとおくと N={(ar)^l}*{br}^m =(a^l)*(b^m)*r^(l+m) Nの正の約数の総和は S=((a^0)+(a^1)+…(a^l)) ((b^0)+(b^1)+…(a^m)) ((r^0)+(r^l)+…(r^(l+m))) から {1-a^(l+1)}/1-a * {1-b^(m+1)}/1-b *{1-r^(l+m+1)}/1-r になりますが 等比数列の和を利用して{1-a^(l+1)}/1-a になるそうですが(l+1)がどのようにして現れたのか分かりません。

  • 約数

    144の正の約数は□個であり、それらの和は□である という問題で 約数は 1,2,3,4,5,6,8,9,12,16,24,36,48,72,144 とわかったのですが、 早く見つけ出すコツ(方法)はありますか?

  • 6の約数

    現在学生で数学を勉強中です。 非常に低レベルですが、質問させて下さい。 6の正の約数は1,2,3,6ですが、6の約数は?と聞かれた場合、答えはどうなるのでしょうか。 深く考え込みすぎて頭の中がこんがらがってきてしまいました。 どなたか教えてくださると助かります。

  • 12345679の約数を知りたい

    この数は37で割り切れることまでわかったのですが、その商333667はまだ約数があるのですか。これあってますか?(自信がないので) 約数を調べるソフトがあるそうですが、もしあるのならその名前も教えてください。

  • 約数

    自然数aの全ての約数の積が 自然数bの全ての約数の積に 等しいとき、a=b ですか?

  • 約数の問題

    約数の問題です。 504の正の約数の総和を求める問題です。 やろうと思えば全部書き出せばできるのですが簡単なやり方というのはないのですか?あるなら是非教えてください。

専門家に質問してみよう