Table of Contents
Problem: Angular Bisector and Tangent
Problem
辺の長さが整数で BC ≤ AC ≤ AB を満たす三角形 ABC がある. k は角 ACB の二等分線である. m は ABC の外接円に対する C での接線である. n は B を通る m に平行な線である. n と k の交点を E とする.
BE の長さが整数で周長が 100 000 を超えない三角形 ABC はいくつあるか?
この問題は計算は大変ですが, 解答方針の立て方自体は三角形の相似と内角の二等分線の性質を利用するだけという 良問です.
解答方針を立てるまで
Python Solution
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import math
class Solution:
"""
Problem
https://projecteuler.net/problem=296
Solution
Using the similarity between the triangle ACD and BCE
and BE = BD
Usage
Solver = Solution()
Solver.find_solution()
>>> 1137208419
"""
def gcd(self, a, b):
while b > 0:
a, b = b, a % b
return a
#def check_length(self, AB, AC, BC):
# return BC <= AC & AC <= AB
def find_solution(self, perimeter:int=100000):
count = 0
for BC in range(1, perimeter//3 + 1):
for AC in range(BC, (perimeter - BC)//2 + 1):
k = self.gcd(AC, BC)
step = AC//k + BC//k
min_AB = math.ceil(AC / step) * step
max_AB = min(AC + BC, perimeter - AC - BC + 1)
count += math.ceil((max_AB - min_AB) / step)
return count
実行時間が遅い問題について
実行時間が遅い問題に直面した場合,
- アルゴリズムの改善
- マルチコアとメモリの暴力で殴る
という対応策が考えられます. 今回は「マルチコアとメモリの暴力で殴る」の方針での対応策を採用します. そもそも, 上記で紹介した解答を実行時のシステムモニターを見てみると, 少なくとも僕の場合はCPU1コアのみが稼働している状態となっていたので, これを30コアにすればオーバヘッドが発生するかもしれませんが, 単純に20~30倍近くの実行スピードが確保できると期待できます.
###
Python code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import math
from multiprocessing import Pool
class Solution:
"""
Note
faster version using the multiprocessing module
Problem
https://projecteuler.net/problem=296
Solution
Using the similarity between the triangle ACD and BCE
and BE = BD
Usage
Solver = Solution()
Solver.find_solution()
>>> 1137208419
"""
def gcd(self, a, b):
while b > 0:
a, b = b, a % b
return a
def compute(self, BC):
count = 0
for AC in range(BC, (self.perimeter - BC)//2 + 1):
k = self.gcd(AC, BC)
step = AC//k + BC//k
min_AB = math.ceil(AC / step) * step
max_AB = min(AC + BC, self.perimeter - AC - BC + 1)
count += math.ceil((max_AB - min_AB) / step)
return count
def find_solution(self, cpu, perimeter:int=100000):
self.perimeter = perimeter
with Pool(processes=cpu) as pool:
return sum(pool.map(Solver.compute, range(1, perimeter//3 + 1)))
Solver = Solution()
Solver.find_solution(cpu=30, perimeter=100000)
爆速の実行スピードが確保できるようになった.
References
- Project Euler Problem 296
- GitHub > problem_0296_angular_bisector_and_tangent.py
- GitHub > problem_0296_angular_bisector_and_tangent_2.py
統計
Python
math
Linux
Ubuntu 20.04 LTS
Shell
English
git
方法論
Ubuntu 22.04 LTS
統計検定
競技プログラミング
フーリエ解析
前処理
SQL
coding
コミュニケーション
Network
ssh
将棋
Data visualization
Docker
Econometrics
VSCode
statistical inference
GitHub Pages
apt
development
システム管理
Coffee
cloud
数値計算
素数
Book
Font
Metrics
Poetry
Ubuntu 24.04 LTS
architecture
aws
shell
systemctl
テンプレート
データ構造
ポワソン分布
会計分析
文字コード
環境構築
論文
App
Bayesian
Dynamic Programming
Keyboard
Processing
R
Steam
filesystem
quarto
regex
(注意:GitHub Accountが必要となります)