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.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で質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# c言語 コマンドライン引数 4 2023/02/09 18:47
- HTML・CSS HTMLの・要素・属性・属性値 はプログラム言語の「変数」みたいに変更できますか? 5 2022/10/04 05:27
- オープンソース IT用語、ソースとオブジェクト、改変と翻訳と翻案の違いなど どのようにりかいすればよいのですか 1 2022/09/09 10:02
- その他(ビジネス・キャリア) グーグルの障害者訓練プログラム募集あるがどうだろ?6時間勤務で月収22万!! 1 2023/02/17 20:36
- C言語・C++・C# C言語 3 2022/10/04 15:07
- その他(プログラミング・Web制作) Arduino UNO のC言語 2 2023/04/18 19:42
- C言語・C++・C# C#の問題で2つの整数a,bの最大公約数(GCD)を求めるユークリッドの互除法は,aをbで割った余り 2 2022/06/26 16:52
- C言語・C++・C# 変数の初期化について 5 2022/10/02 08:55
- C言語・C++・C# C言語初心者 構造体 課題について 2 2023/03/10 19:48
- Ruby VBA 2 2023/01/14 14:14
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
配列数式の解除
-
VBのFunctionで、配列を引数...
-
VBA 1次元配列を2次元に追加する
-
subの配列引数をoptionalで使う...
-
Excel VBA配列をFunctionに渡す
-
C言語のプログラミングについて...
-
配列変数の添字が範囲外ですと...
-
VB6 配列を初期化したい
-
特定のセル範囲で4文字以上入力...
-
2次元動的配列の第一引数のみを...
-
ListViewで、非表示列って作れ...
-
Excel VBA 2次元配列...
-
for each の現在の配列ポインタ...
-
Excel-VBAの配列「Public Const...
-
配列の内容に重複をなくすには...
-
COBOL 2次元配列について
-
シェルスクリプト中で、ヒアド...
-
行列の積の計算プログラムを教...
-
AES暗号にて、AES_set_encrypt_...
-
2つ以上の変数を比較して最大数...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
配列数式の解除
-
2つ以上の変数を比較して最大数...
-
for each の現在の配列ポインタ...
-
配列変数の添字が範囲外ですと...
-
VBA 1次元配列を2次元に追加する
-
特定のセル範囲で4文字以上入力...
-
subの配列引数をoptionalで使う...
-
ListViewで、非表示列って作れ...
-
VB6 配列を初期化したい
-
Excel-VBAの配列「Public Const...
-
配列を任意の数値で埋める方法
-
Dim は何の略ですか?
-
verilogで配列の任意の8bitを取...
-
VBのFunctionで、配列を引数...
-
2次元動的配列の第一引数のみを...
-
エクセルで最小値から0を除く方法
-
VBA Match関数の限界
-
Excel VBA配列をFunctionに渡す
-
VB2008: CSV を二次元配列に読...
-
fortranでのcsvファイルの読み込み
おすすめ情報