競技プログラミングをpythonで遊ぶ3[ABC103 C]
コンテストページはこちら↓
C問題なので長めです!
問題文
N個の正整数a1,a2,...,aNが与えられます。
非負整数mに対して、f(m) = (m mod a1) + (m mod a2) + ... + (m mod aN)とします。
ここで、X mod YはXをYで割った余りを表します。
fの最大値を求めてください。
制約
・入力は全て整数である
・2 <= N <= 3000
・2 <= ai <= 10^5
要約
ある数(m)をN個の数字(ai)でそれぞれ割った余りを全部足した時の最大値
タイトルの剰余加算そのままの意味
例3, 4, 6だと、f(11) = (11 mod 3) + (11 mod 4) + (11 mod 6) = 10が最大
最小公倍数-1を剰余すればよさそう
解答
N = int(input())
a = list(map(int, input().split()))
# 最大公約数(greatest_common_divisor)
def gcd(a, b):
if b == 0:
return a
return gcd(b, a%b)
# 最小公倍数(lowest_common_multiple)
def lcm(a, b):
return a*b//gcd(a,b)
# 最小公倍数と、比べていない数字を比べ、最小公倍数を更新する
alcm = a[0]
for i in a[1:]:
alcm = lcm(alcm, i)
res = 0
# 関数f
for i in range(N):
res += (alcm-1) % a[i]
print(res)
参考サイトより最小公倍数の求め方を得る
>>> def gcd(a, b):
... if b == 0:
... return a
... return gcd(b, a%b)
...
>>> def lcm(a, b):
... return a*b//gcd(a,b)
...
>>> lcm(3, 4)
12
>>> lcm(12, 6)
12
ユークリッドの互除法強い
gcdは関数の中で自分を呼び出す再起関数と呼ばれる関数
(問題) 1071 と 1029 の最大公約数を求める。
・1071 を _1029_ で割った余りは 42
・_1029_ を 42 で割った余りは _21_
・42 を _21_ で割った余りは 0
よって、最大公約数は_21_である。
二つの数字(A, B)から導いた結果(C)を使い、同じ計算をしたいときに再起関数を使おう
A%B = C -> B%C = D -> C%D = E
def greatest_common_divisor(a, b):
if b == 0:
return a
return greatest_common_divisor(b, a%b)
でも、今回の困りどころはここではない。
def lcm(a, b):
return a*b//gcd(a,b)
こいつの//が一番必要だった。
>>> a = 1
>>> for i in range(70):
... a *= 99999
...
>>> a
99930024144526916773982970399819677006243826886851248341949435103502365016928159377373102412011786789305356470125308992723524935236237526395803543836650152878130690276548112184320708075952847523963238291960759583049646185441496518267798819550433944907832048337650154662071958518735840420131076787388165843389322659115863969951689445260024149993000001
>>> a / 1
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OverflowError: integer division result too large for a float
理由はこれ、とてつもなく大きい数を普通に割るとfloat型になるときにエラーを吐くのだ...
最大3000個の100000まであり得る数を使うため、それでは困る
そこで、少数のことは考えずに、割ってint型で返してくれる//を使った
>>> a // 1
99930024144526916773982970399819677006243826886851248341949435103502365016928159377373102412011786789305356470125308992723524935236237526395803543836650152878130690276548112184320708075952847523963238291960759583049646185441496518267798819550433944907832048337650154662071958518735840420131076787388165843389322659115863969951689445260024149993000001
>>> 5 / 2
2.5
>>> 5 // 2
2
>>> 100 / 2
50.0
>>> 100 // 2
50
エラー解消!
以上!
この記事が気に入ったらサポートをしてみませんか?