https://school.programmers.co.kr/learn/courses/30/lessons/12927
나만 그런지 모르겠지만, 글을 좀 귀찮게 써놓은 것 같다. 배열 내의 n만큼 요소들의 값을 줄일 수 있고, 배열 내의 숫자를 제곱해서 더했을 때 최솟값을 찾으시오 정도로 쓸 수 있는 게 아닐까.
핵심은 9^2 = 81, 7^2 = 49이므로, 큰 숫자를 먼저 죽이면 된다. 최대 힙을 쓰던가, 그냥 정렬하든가 대충 아무거나. 다만 이 부분에서 살짝 까다로운 게 요소의 값을 변경하면 최댓값이 바뀌기 때문에 좋은 방법을 고안해야 하는 것.
내가 생각한 방법은 정렬하고 '나와 다음 값의 차이' 만큼 값을 빼서 동등하게 만드는 방법. 그런데 이렇게 구현하면 10, [10, 10, 1] 같은 케이스를 실행할 때, n 숫자를 고려하지 않고 그냥 막 빼기 때문에 정답이 망한다.
다음 방법은 그냥 얌전히 1씩 빼는 방법. 나와 다음 숫자가 같으면 1을 빼고 다음 요소로 넘어가고, 다르면 1을 빼고 배열의 첫 번째 요소로 이동한다. 뭔가 산을 꼭대기부터 한 칸 씩 깎는 느낌이다. 1씩 뺀다는 것 자체가 효율성에서 문제가 생길 것 같긴 했는데 왜인지 다 통과했다.

using System;
using System.Linq;
public class Solution {
public long CalcWorksToResult(int[] works)
{
return works.Aggregate<int, long>(0, (current, t) => current + t * t);
}
public long solution(int n, int[] works) {
long answer = 0;
var orderWorks = works.OrderByDescending(i => i).ToArray();
if (works.Length == 1)
{
var result = Math.Max(works[0] - n, 0);
return result * result;
}
var index = 0;
while (0 < n)
{
var a = orderWorks[index];
var b = orderWorks[index + 1];
if (a == b)
{
orderWorks[index] -= 1;
n -= 1;
index++;
}
else if (a > b)
{
orderWorks[index] -= 1;
n -= 1;
index = 0;
}
if (index == works.Length - 1)
{
var value = Math.Min(1, n);
orderWorks[index] -= value;
n -= value;
index = 0;
if (orderWorks[index] == 0)
{
return 0;
}
}
}
return CalcWorksToResult(orderWorks);
}
}
코드가 좀 더러워서 바꾸고 싶지만, 리포트를 써야 하므로...