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が十分大きい場合結果が出るまでに時間がかかり、負荷が高いのでちょっと問題です。
多分、間違いなくもっと良い回答例があるとは思いますが、一例ということでこれでどうでしょうか。
No.2
- 回答日時:
最近ツッコミ専門になりかけている...。
yusuke5111さんのやり方が最も簡単ですね。
ただし、n自体もnの約数なので
for( i=1; i<=n; i++ ){
とすべきですね。
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
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・街中で見かけて「グッときた人」の思い出
- ・「一気に最後まで読んだ」本、教えて下さい!
- ・幼稚園時代「何組」でしたか?
- ・激凹みから立ち直る方法
- ・1つだけ過去を変えられるとしたら?
- ・【あるあるbot連動企画】あるあるbotに投稿したけど採用されなかったあるある募集
- ・【あるあるbot連動企画】フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
- ・映画のエンドロール観る派?観ない派?
- ・海外旅行から帰ってきたら、まず何を食べる?
- ・誕生日にもらった意外なもの
- ・天使と悪魔選手権
- ・ちょっと先の未来クイズ第2問
- ・【大喜利】【投稿~9/7】 ロボットの住む世界で流行ってる罰ゲームとは?
- ・推しミネラルウォーターはありますか?
- ・都道府県穴埋めゲーム
- ・この人頭いいなと思ったエピソード
- ・準・究極の選択
- ・ゆるやかでぃべーと タイムマシンを破壊すべきか。
- ・歩いた自慢大会
- ・許せない心理テスト
- ・字面がカッコいい英単語
- ・これ何て呼びますか Part2
- ・人生で一番思い出に残ってる靴
- ・ゆるやかでぃべーと すべての高校生はアルバイトをするべきだ。
- ・初めて自分の家と他人の家が違う、と意識した時
- ・単二電池
- ・チョコミントアイス
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
配列数式の解除
-
2つ以上の変数を比較して最大数...
-
VBA 1次元配列を2次元に追加する
-
特定のセル範囲で4文字以上入力...
-
配列を任意の数値で埋める方法
-
for each の現在の配列ポインタ...
-
delphiで配列を、コピーするには。
-
配列変数の添字が範囲外ですと...
-
VB2008: CSV を二次元配列に読...
-
ExcelVBA Rangeの扱いについて
-
subの配列引数をoptionalで使う...
-
C++のテーブル検索に関する質問...
-
VB6 配列を初期化したい
-
ListViewで、非表示列って作れ...
-
linest関数に配列を渡す
-
Array配列の末尾に追加したい。
-
配列内の検索方法
-
[VB.net] StringからByte配列へ...
-
VBA Match関数の限界
-
テキストボックスの表示
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
配列数式の解除
-
2つ以上の変数を比較して最大数...
-
VBA 1次元配列を2次元に追加する
-
VB6 配列を初期化したい
-
特定のセル範囲で4文字以上入力...
-
ListViewで、非表示列って作れ...
-
《エクセル2000》A列・B列の商...
-
配列変数の添字が範囲外ですと...
-
Excel-VBAの配列「Public Const...
-
subの配列引数をoptionalで使う...
-
for each の現在の配列ポインタ...
-
配列を任意の数値で埋める方法
-
Dim は何の略ですか?
-
VBのFunctionで、配列を引数...
-
配列内の内容を全て表示する方法
-
2次元動的配列の第一引数のみを...
-
Excel VBA配列をFunctionに渡す
-
VBA Match関数の限界
-
Array配列の末尾に追加したい。
-
AES暗号にて、AES_set_encrypt_...
おすすめ情報