裏 RjpWiki

Julia ときどき R, Python によるコンピュータプログラム,コンピュータ・サイエンス,統計学

「ストレート・ラインズ」問題

2017年11月23日 | ブログラミング

「ストレート・ラインズ」問題

締め切りが 2017/11/23 10:00 AM なので,その 1 分後に投稿されるように予約

設問

2 以上の自然数 n に対し、n×n の格子状に並んだ点を考えます。
これらの点のうちちょうど 2 個の点を通る直線の数を F(n) と定義します。
 
例えば F(2)=6 です。題意を満たす直線は以下の 6 通りです。
 

 
また、F(3)=12 です。題意を満たす直線は以下の 12 通りです。
 

 
同様に、F(4)=48, F(5)=108, F(6)=248, F(7)=428, F(10)=1900 となることが確かめられます。
 
標準入力から、自然数 n (2 ≦ n ≦ 40)が与えられます。
標準出力に F(n) の値を出力するプログラムを書いてください。
 
===================================

問題文中にある数列情報だけで,オンライン整数列大辞典の A018809 であることがわかる。その説明書きが "Number of lines through exactly 2 points of an n X n grid of points." と,問題の趣旨そのものである。
ただ,記事中の (x, y) = 1 というのが何なのか,分からなかったが,関連する論文を読んで,「x, y の最大公約数が 1」ということが分かったのでプログラムを書き下ろす。

euclid = function(m, n) {
    repeat {
        temp = n%%m
        if (temp == 0) {
            return(m)
        }
        n = m
        m = temp
    }
}

g = function(n, k) {
    count = 0
    for (x in 0:n) {
        for (y in 0:n) {
            if (x != 0 && y != 0 && euclid(x, y) == k)
                count = count + (n - x) * (n - y)
        }
    }
    count
}

f = function(n) {
    if (n == 2) {
        cat(6)
    } else {
        cat(2 * g(n, 3) - 4 * g(n, 2) + 2 * g(n, 1))
    }
}

# f(scan(file("stdin", "r")))

#    n: 0  1  2   3   4    5    6    7    8     9    10
# f(n): 0, 0, 6, 12, 48, 108, 248, 428, 764, 1196, 1900
f(13) # 5244
f(27) # 98492
f(38) # 388212
f(40) # 475068

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

PVアクセスランキング にほんブログ村

PVアクセスランキング にほんブログ村