{ }codelper
参数复制列表列表排序P0333

可以接收任意个评分的函数

编写一个求体操比赛动作得分的函数 得分(难度, 舍去数, 各评分)。
难度 d 和舍去数 k 一定会收到,后面的评分可以接收任意个。
函数把收到的评分中最低的 k 个和最高的 k 个舍去,返回剩下评分之和乘以 d 的值。
即使有多个相同的分数,也只从低的一侧舍去 k 个、从高的一侧舍去 k 个。
没有剩下的评分时,和为 0。
每套动作调用这个函数两次。
正式得分把所有裁判的评分传进去,用 得分(d, k, s1, s2, …, sm) 求出。
主裁得分只传入该行最前面两位裁判(主裁)的评分,什么都不舍去,用 得分(d, 0, s1, s2) 求出。
第一行给出动作数 q。
接下来 q 行,每套动作给出 d、k,然后是评分 s1, s2, …, sm,用一个空格隔开。
裁判人数 m 每行可能不同,不另外给出。
每套动作在一行中按这个顺序输出正式得分和主裁得分,用一个空格隔开。
评测只看输出,不检查函数是怎么写的。
不过请试着写一个带有可以接收任意个值的参数(没有这种语法的语言用一个列表或数组)的函数,并调用它两次来解。

输入
1 ≤ q ≤ 1,000。
1 ≤ d ≤ 10。
2 ≤ m ≤ 100。
0 ≤ k 且 2 × k ≤ m。
0 ≤ 评分 ≤ 100(都是整数)
输出
q 行,每行是正式得分和主裁得分
样例 1 · stdin
3
3 1 9 7 8 10
2 0 5 6 7
1 1 4 100
stdout
51 48
36 22
0 104
main.py
输入(stdin)

运行时这些行会依次作为 input()/标准输入传入(运行中不会等待输入)。

$ 就绪

请在电脑上打开以编写和运行代码。在手机上可以查看题目和题解。

其他语言怎么写?查看各语言题解 · 8 种语言题解

接收任意个值的参数,各语言写法不同。
Python def score(d, k, *scores),JS function score(d, k, ...scores),TS ...scores: number[],Java static long score(int d, int k, int... scores),C# static long Score(int d, int k, params int[] scores),一个函数里只能用一次。
在 JS・TS・Java・C# 中它必须是最后一个参数,而 Python 可以在 *scores 后面再写只能按名字传的参数(陷阱 ③)。
C 的 ...(stdarg.h)不知道收到了几个,也不能把数组展开传进去,所以像 (const int *scores, int m) 这样接收数组和个数;C++ 用 std::vector<int> 接收,调用时像 score(d, 0, {s[0], s[1]}) 这样用花括号括起来。
Craykon 没有这种语法,用一个列表接收,像 得分(d, 0, [s[0], s[1]]) 这样调用。
调用的一侧也不同。
Python 的 score(*nums) 和 JS 的 score(...nums) 把列表展开,前两个给 d 和 k,其余给 scores。
TS 会拒绝 score(...nums)(TS2556:不知道展开后有几个落在 d 和 k 的位置)。
所以写成 score(d, k, ...nums.slice(2)),只在剩余参数的位置展开。
Java 和 C# 直接把数组传过去就行。
陷阱 ① 收到的是不是副本,各语言不同。
Python 的 *scores 是新的元组,JS・TS 的 ...scores 是新的数组,所以在函数里排序不会影响调用方。
但把数组传给 Java 的 int... 和 C# 的 params 时不会复制,函数收到的就是那个数组。
Craykon 的列表也一样。
在函数里直接排序会改变调用方数组的顺序,之后用 s[0]、s[1] 取出的主裁评分就成了最低的两个分数(样例第一行的 48 会变成 45)。
用 scores.clone()、(int[])scores.Clone()、Craykon scores.子列表(0, scores.数量) 对副本排序。
C++ 按值接收 vector 就是副本。
② Python 的 *scores 是元组,没有 scores.sort()(AttributeError)。
要用 sorted(scores)。
③ 在 Python 中像 def score(d, *scores, k=0) 这样写在 *scores 后面的参数只能按名字传。
按位置传的 k 会混进评分里。
④ 把舍去后剩下的范围写成 Python 的 ordered[k:-k],k 为 0 时是 [0:0],成了空列表。
要写成 ordered[k:len(ordered) - k]。
⑤ JS・TS 的 sort() 不给比较函数时连数字也按字符串顺序排,10 会排在 9 前面,100 排在 20 前面。
要写成 sort((a, b) => a - b)。

Pythonmain.py · 20 行
import sys  def score(d, k, *scores):    """난도 d와 버림 k는 꼭 받고, 심사 점수는 몇 개든 받는다(scores는 튜플)."""    ordered = sorted(scores)  # 튜플은 고칠 수 없으니 정렬한 새 목록을 만든다    kept = ordered[k:len(ordered) - k]  # [k:-k]는 k가 0일 때 빈 목록이 된다    return d * sum(kept)  lines = sys.stdin.read().split("\n")q = int(lines[0])out = []for i in range(1, q + 1):    nums = list(map(int, lines[i].split()))    d, k = nums[0], nums[1]    official = score(*nums)  # 목록을 펼쳐 넘긴다: 앞의 둘은 d와 k로, 나머지는 scores로    head = score(d, 0, nums[2], nums[3])  # 주심 두 명만 따로 넘긴다    out.append(f"{official} {head}")print("\n".join(out))
JavaScriptmain.js · 19 行
// 난도 d와 버림 k는 꼭 받고, 심사 점수는 몇 개든 받는다(...scores는 새 배열)function score(d, k, ...scores) {  scores.sort((a, b) => a - b); // 비교 함수가 없으면 문자열 순서로 정렬된다  let sum = 0;  for (let i = k; i < scores.length - k; i++) sum += scores[i];  return d * sum;} const lines = require("fs").readFileSync(0, "utf8").split("\n");const q = Number(lines[0]);const out = [];for (let i = 1; i <= q; i++) {  const nums = lines[i].trim().split(/\s+/).map(Number);  const [d, k] = nums;  const official = score(...nums); // 배열을 펼쳐 넘긴다: 값이 복사되므로 nums는 그대로다  const head = score(d, 0, nums[2], nums[3]); // 주심 두 명만 따로 넘긴다  out.push(official + " " + head);}console.log(out.join("\n"));
TypeScriptmain.ts · 22 行
import { readFileSync } from "node:fs"; // 난도 d와 버림 k는 꼭 받고, 심사 점수는 몇 개든 받는다(...scores는 새 배열)function score(d: number, k: number, ...scores: number[]): number {  scores.sort((a, b) => a - b); // 비교 함수가 없으면 문자열 순서로 정렬된다  let sum = 0;  for (let i = k; i < scores.length - k; i++) sum += scores[i];  return d * sum;} const lines: string[] = readFileSync(0, "utf8").split("\n");const q: number = Number(lines[0]);const out: string[] = [];for (let i = 1; i <= q; i++) {  const nums: number[] = lines[i].trim().split(/\s+/).map(Number);  const [d, k] = nums;  // score(...nums)는 d와 k 자리에 몇 개가 들어갈지 몰라 TS가 막는다: 나머지 매개변수 자리만 펼친다  const official: number = score(d, k, ...nums.slice(2));  const head: number = score(d, 0, nums[2], nums[3]); // 주심 두 명만 따로 넘긴다  out.push(official + " " + head);}console.log(out.join("\n"));
JavaMain.java · 32 行
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.util.Arrays; public class Main {    // 난도 d와 버림 k는 꼭 받고, 심사 점수는 몇 개든 받는다(int...은 맨 뒤에만 쓸 수 있다)    static long score(int d, int k, int... scores) {        // 배열을 그대로 넘겨받으면 부른 쪽 배열과 같은 것이다: 복사본을 정렬한다        int[] ordered = scores.clone();        Arrays.sort(ordered);        long sum = 0;        for (int i = k; i < ordered.length - k; i++) sum += ordered[i];        return d * sum;    }     public static void main(String[] args) throws IOException {        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));        int q = Integer.parseInt(in.readLine().trim());        StringBuilder out = new StringBuilder();        for (int line = 0; line < q; line++) {            String[] parts = in.readLine().trim().split("\\s+");            int d = Integer.parseInt(parts[0]), k = Integer.parseInt(parts[1]);            int[] s = new int[parts.length - 2];            for (int i = 0; i < s.length; i++) s[i] = Integer.parseInt(parts[i + 2]);            long official = score(d, k, s);        // 배열을 통째로 넘긴다            long head = score(d, 0, s[0], s[1]);   // 주심 두 명만 따로 넘긴다            out.append(official).append(' ').append(head).append('\n');        }        System.out.print(out);    }}
C#Main.cs · 33 行
using System;using System.Text; class Program{    // 난도 d와 버림 k는 꼭 받고, 심사 점수는 몇 개든 받는다(params는 맨 뒤에만 쓸 수 있다)    static long Score(int d, int k, params int[] scores)    {        // 배열을 그대로 넘겨받으면 부른 쪽 배열과 같은 것이다: 복사본을 정렬한다        int[] ordered = (int[])scores.Clone();        Array.Sort(ordered);        long sum = 0;        for (int i = k; i < ordered.Length - k; i++) sum += ordered[i];        return d * sum;    }     static void Main()    {        int q = int.Parse(Console.ReadLine());        var sb = new StringBuilder();        for (int line = 0; line < q; line++)        {            string[] parts = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries);            int d = int.Parse(parts[0]), k = int.Parse(parts[1]);            int[] s = new int[parts.Length - 2];            for (int i = 0; i < s.Length; i++) s[i] = int.Parse(parts[i + 2]);            long official = Score(d, k, s);        // 배열을 통째로 넘긴다            long head = Score(d, 0, s[0], s[1]);   // 주심 두 명만 따로 넘긴다            sb.Append(official).Append(' ').Append(head).Append('\n');        }        Console.Write(sb);    }}
C++main.cpp · 30 行
#include <algorithm>#include <iostream>#include <sstream>#include <string>#include <vector> // 심사 점수는 vector로 받는다. 값으로 받으면 복사본이라 마음대로 정렬해도 된다static long long score(int d, int k, std::vector<int> scores) {    std::sort(scores.begin(), scores.end());    long long sum = 0;    for (int i = k; i < static_cast<int>(scores.size()) - k; i++) sum += scores[i];    return d * sum;} int main() {    std::string line;    std::getline(std::cin, line);    int q = std::stoi(line);    for (int t = 0; t < q; t++) {        std::getline(std::cin, line);        std::istringstream in(line);        int d, k, x;        in >> d >> k;        std::vector<int> s;        while (in >> x) s.push_back(x);        long long official = score(d, k, s);        long long head = score(d, 0, {s[0], s[1]}); // 주심 두 명만 중괄호로 묶어 넘긴다        std::cout << official << ' ' << head << '\n';    }}
Cmain.c · 41 行
#include <stdio.h>#include <stdlib.h>#include <string.h> #define MAXM 100 static int by_value(const void *a, const void *b) {    return *(const int *)a - *(const int *)b;} /* C의 ...(stdarg.h)는 개수를 알 수 없고 배열을 펼쳐 넘길 수도 없다: 배열과 개수를 함께 받는다 */static long long score(int d, int k, const int *scores, int m) {    int ordered[MAXM];    memcpy(ordered, scores, (size_t)m * sizeof(int)); /* 부른 쪽 배열은 그대로 둔다 */    qsort(ordered, (size_t)m, sizeof(int), by_value);    long long sum = 0;    for (int i = k; i < m - k; i++) sum += ordered[i];    return d * sum;} int main(void) {    int q;    static char line[1024];    scanf("%d ", &q);    for (int t = 0; t < q; t++) {        if (!fgets(line, sizeof line, stdin)) break;        int d, k, used = 0, m = 0, s[MAXM];        char *p = line;        sscanf(p, "%d %d%n", &d, &k, &used);        p += used;        while (m < MAXM && sscanf(p, "%d%n", &s[m], &used) == 1) {            p += used;            m++;        }        long long official = score(d, k, s, m);        int heads[2] = {s[0], s[1]}; /* 주심 두 명만 따로 넘긴다 */        long long head = score(d, 0, heads, 2);        printf("%lld %lld\n", official, head);    }    return 0;}
Craykonmain.cray · 26 行
// 크레이콘에는 '몇 개든 받는 매개변수'가 없다 — 심사 점수를 목록 하나로 받는다점수(d, k, scores){    // 받은 목록은 부른 쪽 목록과 같은 것이다: 복사본을 정렬한다    ordered = scores.子列表(0, scores.数量);    ordered.排序();    sum = 0;    循环 (i = k; i < ordered.数量 - k; i++)    {        sum += ordered[i];    }    返回 d * sum;} q = 控制台.读行().转数字();循环 (t = 0; t < q; t++){    nums = 控制台.读数字();    d = nums[0];    k = nums[1];    s = nums.子列表(2, nums.数量 - 2);    official = 점수(d, k, s);    // 주심 두 명만 새 목록으로 묶어 넘긴다    head = 점수(d, 0, [s[0], s[1]]);    控制台.输出(official + " " + head);}