- ベストアンサー
約数のプログラミングです
TAGOSAKU7の回答
- TAGOSAKU7
- ベストアンサー率65% (276/422)
以下に処理の流れとプログラムを記します。プログラムと照らし合わせて読んでください。 約数とは、「因数を掛け合わせたもの」ですよね? だからまず因数を求める関数を作成しました。(関数: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
関連するQ&A
- 約数の個数
私が今使っている参考書の数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)(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)がどのようにして現れたのか分かりません。
- ベストアンサー
- 数学・算数
- 約数
与えられた自然数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 になることわ分かりません。
- 締切済み
- 数学・算数
- 12345679の約数を知りたい
この数は37で割り切れることまでわかったのですが、その商333667はまだ約数があるのですか。これあってますか?(自信がないので) 約数を調べるソフトがあるそうですが、もしあるのならその名前も教えてください。
- ベストアンサー
- 数学・算数