東北大学 2020年 前期数学試験（理系）大問１～３をPythonで解いてみた



はじめまして、MatLaserです！
記念すべきQiita初投稿です、よろしくお願いします！
普段は研究でPythonを使っていますが、最近は様々な技術に興味が出てきてちょっとずつ勉強してます。
本投稿は前々から一度やってみたいと思っていて、GWは時間もあり、良い機会ということで書いてみました。
技術不足・知識不足のため、効率の悪いコーディングや誤った理解等あると思いますが、初心者がアウトプットするために書いているので、暖かい目で見ていただけると幸いです。

なお、問題と解答のpdfはこちらにあるので、適宜参照してください。
本記事でも基本的には解答の解き方に沿ってコーディングしていきます。

　[問題](https://www.kahoku.co.jp/special/exam2020_tohokudai/sugaku_rikei_q.pdf)
　[解答1,4,5,6](https://www.kahoku.co.jp/special/exam2020_tohokudai/sugaku_rikei_a.pdf)
　[解答2,3](https://www.kahoku.co.jp/special/exam2020_tohokudai/sugaku_bunkei_a.pdf)
# 第一問
(1) 余弦定理を使うだけですね。

(2) 三点A,B,Cの座標設定をうまくとることで、変数$s$の存在を点Pの$y$座標のみにでき、若干計算が楽になりますね。

以下、解答画像です。
![スクリーンショット (120).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/573147/49f1e580-2cff-0c2a-7e0a-48ebfb4dd600.png)

それではコーディングしていきます。

```python:1.py

# 初期条件
ab = 1
ac = 1
bc = 0.5

import numpy as np

# (１)
# 余弦定理
cos_theta = (ab**2 + ac**2 - bc**2) / (2 * ab * ac)
sin_theta = np.sqrt(1 - cos_theta**2)
print(cos_theta, sin_theta) # 0.875 0.484 = 7/8 (√15)/8

# (2)
# func = AP^2 + BP^2 + CP^2 とする
def func(s):
    return 25/32 + 15/64 * ((3 * (s - 2/3)**2) + 2/3)

lis = [] # 変数 s と その時の func の値をタプルとして収納するリスト

# 0<s<1 を 0.01 ずつ変化させ、全探索
for s in np.arange(0,1,0.01):
    value = func(s)
    lis.append((s, value))

print(lis)
# min_value でソートし、最初の要素を出力
lis_sort = sorted(lis, key=lambda values: values[1])
print(lis_sort[0]) # (s, min_value) = (0.67, 0.9375)

```

# 第二問
(1) 素直に直線L、Mの交点を求めて、円Cに代入ですね。

(2) 円Cの中心と直線Lの距離が、円Cの半径(a)よりも小さい時に題意を満たしますね。

(3) (2)と同様、点と直線の距離と円Cの半径を比較することで共有店の個数を求め、あとは愚直に調べるだけですね。
　これは(2)の不等号を変えるだけなので省略します。

以下、解答画像です。
![スクリーンショット (121).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/573147/dc9e8521-93b1-acbf-0259-d726b96b1032.png)


それではコーディングしていきます。

```python:2.py

import sympy
x = sympy.Symbol('x')
y = sympy.Symbol('y')
a = sympy.Symbol('a')

# (1)
expr1 = -4 * x + 3 * y + a
expr2 = 3 * x + 4 * y - 7 * a
d = sympy.solve([expr1, expr2], [x,y])
# print(d) # 直線L、Mの交点が (a, a) とわかる

# 円Cに（a, a）を代入
sympy.var('x, y, a')
x = d[x] # xに上で得た交点のx座標代入
y = d[y] # yに上で得た交点のy座標代入
sol = sympy.solve (1 * x**2 - 2 * a * x + y**2 - 4 * y + 4, a)
sympy.init_printing()
print(sol) # 解答のリスト（今回は 1 のみ）取得

# (2)
# 不等号の解はIntervalで区間の型にして、和集合を取ればよいが、今回は等式から境界値を求めて終わる
dis = abs(6 - 3 * a)/5
# dis^2 = abs(a)を両辺二乗して解く
expr3 = 16 * a**2 + 36 * a - 36
d2 = sympy.solve([expr3])
print(d2) # [{a: -3}, {a: 3/4}] 共有店の個数が変化する境界値

# (3)
# 省略

```

# 第三問
(1) 問題文を見て、パッと思い浮かぶ解法として、以下の三つがあると思います。
    　・数学的帰納法
    　・式変形による不等式の導出
    　・関数化：$f(n)=3^n-(2^n+n^2+8)$ として、$n≧3$ で $f(n)>0$ であることを示す
　解答では数学的帰納法を用いていますが、プログラミングで解くという観点から言うと、関数化が一番簡単だと思います。

(2) (1)で $n≧3$ で $f(n)>0$ であることを示しているので、$f(n)≦0$ となるためには、少なくとも $n<3$ である必要があります。また今回 $n$ は正の整数という条件があるため、$n=1,2$ が解の候補であることがわかります。ここまでわかれば、あとは実際に代入して題意が成立するか確かめるだけですね。

(3) $a,b,n$全て0以上であるため、等式 $2^n+n^2+8=3^n+an+b$ が成立するのは、$n=1$ or $2$ のみ。

以下、解答画像です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/573147/62a52f99-2936-75dd-b87f-c10f7b74aad9.png)

それではコーディングしていきます。

```python:3.py

# (1)
import math

# f(n)
def func(n):
    return 3**n - (2**n + n**2 + 8)

# f'(n)
def func_p1(n):
    return 3**n * math.log(3) - (2**n * math.log(2) + 2 * n)

# f''(n)
def func_p2(n):
    return 3**n * math.log(3)**2 - 2**n * math.log(2)**2

# print(func_p2(3)) # 28.74 ← 0以上
# かつ n > 3 で func_p2(n) >0 （∵ 3**n >> 2**n）

# よって n > 3 で func_p1(n) は単調増加 ...(1)
# また print(func_p1(3)) # 18.11 ← 0以上 ...(2)

# (1),(2)より n > 3 で func(n)も単調増加 ...(3)
# さらに print(func(3)) # 2 ← 0以上 ...(4)

# したがって、(3),(4)より n >= 3 で func(n) > 0 
# Q.E.D

# (2)
print(func(1), func(2)) # -8 -7 よって f(n) < 0 、ゆえに題意を満たす n は 1,2

# (3)

lis = [] # 解リスト
for a in range(9): # n,a,b >= 0 より、a,b は 0~8 で回せば十分
    for b in range(9):
        # n=1の時
        jouken1 = a + b # joken1 = 8

        # n=2の時
        jouken2 = 2 * a + b # joken2 = 7

        if jouken1 == 8:
            lis.append((a,b,1))
        elif jouken2 == 7:
            lis.append((a,b,2))
        else:
            continue

print(lis)
#[(0, 7, 2), (0, 8, 1), (1, 5, 2), (1, 7, 1), (2, 3, 2), (2, 6, 1), (3, 1, 2), (3, 5, 1), (4, 4, 1), (5, 3, 1), (6, 2, 1), (7, 1, 1), (8, 0, 1)]

```


今回はここで終了したいと思います。
残りの問題も暇すぎて死にそうになったらやるかもしれませんww
初めてPythonを用いて連立方程式を解いたのですが、素晴らしいですね。
本当に何でも出来ちゃいます、Python凄い！
またやってみたいもの、面白そうなものが浮かんだら、ゆるーくやっていこうと思います。

ご覧いただき、ありがとうございました。