公式
B - 円形公園の街灯 / Street Lights in a Circular Park 解説
by
B - 円形公園の街灯 / Street Lights in a Circular Park 解説
by
kyopro_friends
角度に変換するために \(\frac{360}{N}\) を掛けるのは最後にやれば十分なので、\(\max_k d(i,S_k)\) の最小化を考えます。
以下、柱の添字は \(\bmod N\) で考えることにします。
\(D_i:=\max_k d(i,S_k)\) は、全てのベンチが \([i-D_i,i+D_i]\) の範囲に収まっていることを意味します。よって、\(D_i\) を最小化するには、全てのベンチを含む最小の区間が求まれば十分です。そのような区間は明らかに、円周全体から、隣り合うベンチが最も遠い区間を除いたものになります。
よって、\(S_k\) をソートしたうえで \(D'=\max_k d(S_k,S_{k+1})\) とすると、\(\min_i D_i=\left\lceil\frac{N-D'}{2}\right\rceil\) とわかります。これはソートと合わせて \(O(M\log M)\) で求めることができます。
答えを既約分数として出力するには、分子と分母をそれぞれ管理し、最後にそれらの最大公約数で割ればよいです。
実装例 (C++)
#include<bits/stdc++.h>
using namespace std;
int main(){
int n, m;
cin >> n >> m;
vector<int> s(m);
for(int i=0; i<m; i++) cin >> s[i];
sort(s.begin(), s.end());
int ans = (s[0]+n) - s[m-1];
for(int i=0; i<m-1; i++){
ans = max(ans, s[i+1] - s[i]);
}
long long nume = (long long)(n - ans + 1) / 2 * 360;
long long deno = n;
long long g = __gcd(nume, deno);
nume /= g;
deno /= g;
cout << nume << "/" << deno << endl;
}
実装例 (Python)
import math
N, M = map(int, input().split())
S = list(map(int, input().split()))
S.sort()
ans = (S[0]+N) - S[-1]
for i in range(M-1):
ans=max(ans, S[i+1] - S[i])
nume = (N - ans + 1) // 2 * 360
deno = N
g = math.gcd(nume, deno)
nume //= g
deno //= g
print(f"{nume}/{deno}")
投稿日時:
最終更新:
