d(n) を n の真の約数の和と定義する. (真の約数とは n 以外の約数のことである. )
もし, d(a) = b かつ d(b) = a (a ≠ b のとき) を満たすとき, a と b は友愛数(親和数)であるという.
例えば, 220 の約数は 1, 2, 4, 5, 10, 11, 20, 22, 44, 55, 110 なので d(220) = 284 である.
また, 284 の約数は 1, 2, 4, 71, 142 なので d(284) = 220 である.
それでは10000未満の友愛数の和を求めよ.
もし, d(a) = b かつ d(b) = a (a ≠ b のとき) を満たすとき, a と b は友愛数(親和数)であるという.
例えば, 220 の約数は 1, 2, 4, 5, 10, 11, 20, 22, 44, 55, 110 なので d(220) = 284 である.
また, 284 の約数は 1, 2, 4, 71, 142 なので d(284) = 220 である.
それでは10000未満の友愛数の和を求めよ.
素因数分解をして, すべての約数を求めれば, 友愛数を計算できます.
- 素因数分解し, すべての約数を求める.
- すべての約数の和を求めて, dを計算する.
- dを計算した結果から, 友愛数を求める.
長くなりますが, 定義した手続きは次のとおりです.
(require srfi/1) (define (square n) (* n n)) (define (divides? a b) (= (remainder b a) 0)) (define (find-divisor n test-divisor) (cond ((> (square test-divisor) n) n) ((divides? test-divisor n) test-divisor) (else (find-divisor n (+ test-divisor 1))))) (define (smallest-divisor n) (find-divisor n 2)) ;; 素因数分解 (define (prime-factorization n) (let ((a (smallest-divisor n))) (if (= a n) (list n) (cons a (prime-factorization (/ n a)))))) ;; sizeの数の変数を持つ真理値表を作る (define (0-1-table size) (define (loop ans n) (if (= n 0) ans (loop (append (map (lambda (lst) (cons #f lst)) ans) (map (lambda (lst) (cons #t lst)) ans)) (- n 1)))) (loop '(()) size)) ;; リストから集合を作る. つまり重複する要素を取り除く. (define (make-set items) (define (loop ans rest) (cond ((null? rest) ans) ((find (lambda (a) (= (car rest) a)) ans) (loop ans (cdr rest))) (else (loop (cons (car rest) ans) (cdr rest))))) (loop '() items)) ;; すべての約数を求める. (define (all-divisor nbr) (let* ((pf (prime-factorization nbr)) (tbl (0-1-table (length pf)))) (sort (make-set (map (lambda (row) (apply * (map (lambda (a b) (if a 1 b)) row pf))) tbl)) <))) ;; 友愛数を求める (define (d n) (- (fold + 0 (all-divisor n)) n)) (define d-list (map (lambda (n) (list n (d n))) (iota 10000 1))) (define a-list (filter (lambda (pair) (and (not (equal? pair (reverse pair))) (member pair d-list))) (map reverse d-list)))
計算してみます.
ようこそ DrRacket, バージョン 5.3.3 [3m]. 言語: Pretty Big; memory limit: 2048 MB. > (make-set (apply append a-list)) (6232 6368 5020 5564 2620 2924 1184 1210 220 284) > (+ 6232 6368 5020 5564 2620 2924 1184 1210 220 284) 31626 >
0 件のコメント:
コメントを投稿