文具店有 n 本笔记本和 m 支笔,各有价格。 笔记本和笔按给出的顺序从 1 开始编号。 今天只有价格不低于 T 的笔记本减 d。 价格低于 T 的笔记本价格不变。 一本笔记本和一支笔组成一个礼品套装。 套装的价格是减价后的笔记本价格加上笔的价格。 请依次输出下面三项。 第一,在一行里按给出的顺序输出减价后的 n 个笔记本价格。 第二,在一行里输出价格不超过 B 的套装数量,然后每行一个输出这些套装:笔记本编号、笔的编号、套装价格。 套装按笔记本编号从小到大输出,笔记本编号相同时按笔的编号从小到大输出。 第三,在一行里从小到大输出价格不超过 B 的套装的价格,相同的价格只输出一次。 如果没有这样的套装,输出 -。 一行里输出多个数时,用一个空格隔开。 这道题是练习由列表生成新列表的简短写法(Python 的推导式,其他语言的 map、filter 等),但评测只看输出,所以用循环来做也可以。
输入
第一行给出 n、m、B、T、d,用一个空格隔开。 第二行给出 n 个笔记本价格,第三行给出 m 个笔的价格,用一个空格隔开。 1 ≤ n, m ≤ 60,每个价格在 1 到 100,000 之间,1 ≤ B ≤ 200,000,1 ≤ d < T ≤ 100,000。 所有数都是整数
输出
第一行输出减价后的 n 个笔记本价格,第二行输出价格不超过 B 的套装数量,接着每个套装一行:笔记本编号、笔的编号、套装价格,最后一行输出各不相同的套装价格(没有则输出 -)。 数只输出数字,不带逗号
Python 的推导式用一行由列表生成新列表。 改变值的 [p - d if p >= T else p for p in notes]、两层循环并筛选的 [... for i ... for j ... if ...]、把相同的值合成一个的集合推导式 {t for ...},就是这道题的三行。 其他语言用别的工具做同样的事。 JS、TS 用 map、flatMap、filter 和 new Set,Java 用流的 map、flatMap、filter、distinct、sorted,C# 用 LINQ 的 Select 和 from … from … where … select,以及 Distinct、OrderBy。 C++ 只在改变值时用 transform,两层的部分用 for 循环,并收集到 std::set 里。 C 和 Craykon 没有这种写法,就用循环往空数组、空列表里一个一个放(Craykon 添加),排序之后(C qsort,Craykon 排序)跳过和前一个相同的值。 陷阱一:在 Python 推导式里,if 的位置决定它的意思。 for 前面的 a if 条件 else b 是选择值的表达式,所有元素都留下;for 后面的 if 是筛选条件,元素会变少。 在示例中写成 [p - d for p in notes if p >= T],600 的笔记本就不见了,第一行变成 1000 800。 陷阱二:写两个 for 时,左边的是外层循环。 调换顺序后笔成了外层,示例中 3 1 1100 会排在 2 2 1100 前面。 C# LINQ 的两个 from 也是同样的顺序。 陷阱三:花括号 {...} 是集合,方括号 [...] 是列表。 写成方括号,相同的值会原样留下,示例的最后一行变成 900 1100 1100 1300 1300。 陷阱四:JS、TS 的 sort() 不给比较函数时,会把数变成字符串按字典序比较。 示例的最后一行会变成 1100 1300 900,所以要写 sort((x, y) => x - y)。 Python 的 sorted、Java 的 sorted、C# 的 OrderBy、Craykon 的 排序 都按数的大小比较。
Pythonmain.py · 21 行
import syslines = sys.stdin.read().split("\n")n, m, B, T, d = map(int, lines[0].split())notes = list(map(int, lines[1].split()))pens = list(map(int, lines[2].split()))# 조건식은 for 앞에: 모든 공책이 남고 값만 바뀐다sale = [p - d if p >= T else p for p in notes]# for 두 개는 적힌 차례대로 바깥 → 안쪽, 뒤의 if는 거르는 조건pairs = [(i, j, a + b) for i, a in enumerate(sale, 1) for j, b in enumerate(pens, 1) if a + b <= B]# 집합 내포로 같은 값을 하나로 모은다totals = sorted({t for _, _, t in pairs})out = [" ".join(map(str, sale)), str(len(pairs))]out += [f"{i} {j} {t}" for i, j, t in pairs]out.append(" ".join(map(str, totals)) if totals else "-")print("\n".join(out))
JavaScriptmain.js · 18 行
const lines = require("fs").readFileSync(0, "utf8").split("\n");const [n, m, B, T, d] = lines[0].trim().split(" ").map(Number);const notes = lines[1].trim().split(" ").map(Number);const pens = lines[2].trim().split(" ").map(Number);// map: 모든 공책이 남고 값만 바뀐다const sale = notes.map((p) => (p >= T ? p - d : p));// flatMap으로 두 겹을 한 줄로 펴고, filter로 거른다const pairs = sale .flatMap((a, i) => pens.map((b, j) => [i + 1, j + 1, a + b])) .filter(([, , t]) => t <= B);// Set으로 같은 값을 하나로 모으고, 수로 견주어 정렬한다const totals = [...new Set(pairs.map(([, , t]) => t))].sort((x, y) => x - y);const out = [sale.join(" "), String(pairs.length)];for (const [i, j, t] of pairs) out.push(`${i} ${j} ${t}`);out.push(totals.length > 0 ? totals.join(" ") : "-");console.log(out.join("\n"));
TypeScriptmain.ts · 22 行
import { readFileSync } from "node:fs";const lines: string[] = readFileSync(0, "utf8").split("\n");const [, , B, T, d]: number[] = lines[0].trim().split(" ").map(Number);const notes: number[] = lines[1].trim().split(" ").map(Number);const pens: number[] = lines[2].trim().split(" ").map(Number);type Pair = [number, number, number];// map: 모든 공책이 남고 값만 바뀐다const sale: number[] = notes.map((p) => (p >= T ? p - d : p));// flatMap으로 두 겹을 한 줄로 펴고, filter로 거른다const pairs: Pair[] = sale .flatMap((a, i) => pens.map((b, j): Pair => [i + 1, j + 1, a + b])) .filter(([, , t]) => t <= B);// Set으로 같은 값을 하나로 모으고, 수로 견주어 정렬한다const totals: number[] = [...new Set(pairs.map(([, , t]) => t))].sort((x, y) => x - y);const out: string[] = [sale.join(" "), String(pairs.length)];for (const [i, j, t] of pairs) out.push(`${i} ${j} ${t}`);out.push(totals.length > 0 ? totals.join(" ") : "-");console.log(out.join("\n"));
JavaMain.java · 41 行
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.util.Arrays;import java.util.stream.Collectors;import java.util.stream.IntStream;public class Main { static int[] readInts(BufferedReader in) throws IOException { return Arrays.stream(in.readLine().trim().split(" ")).mapToInt(Integer::parseInt).toArray(); } public static void main(String[] args) throws IOException { BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); int[] head = readInts(in); int n = head[0], m = head[1], B = head[2], T = head[3], d = head[4]; int[] notes = readInts(in); int[] pens = readInts(in); // 스트림의 map: 모든 공책이 남고 값만 바뀐다 int[] sale = Arrays.stream(notes).map(p -> p >= T ? p - d : p).toArray(); // 두 겹은 flatMap으로 펴고 filter로 거른다 int[][] pairs = IntStream.range(0, n).boxed() .flatMap(i -> IntStream.range(0, m).mapToObj(j -> new int[] {i + 1, j + 1, sale[i] + pens[j]})) .filter(p -> p[2] <= B) .toArray(int[][]::new); // distinct로 같은 값을 하나로 모으고 sorted로 정렬한다 int[] totals = Arrays.stream(pairs).mapToInt(p -> p[2]).distinct().sorted().toArray(); StringBuilder out = new StringBuilder(); out.append(Arrays.stream(sale).mapToObj(String::valueOf).collect(Collectors.joining(" "))).append('\n'); out.append(pairs.length).append('\n'); for (int[] p : pairs) { out.append(p[0]).append(' ').append(p[1]).append(' ').append(p[2]).append('\n'); } out.append(totals.length > 0 ? Arrays.stream(totals).mapToObj(String::valueOf).collect(Collectors.joining(" ")) : "-"); System.out.println(out); }}
C#Main.cs · 34 行
using System;using System.Linq;using System.Text;class Program{ static int[] ReadInts() => Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToArray(); static void Main() { int[] head = ReadInts(); int n = head[0], m = head[1], B = head[2], T = head[3], d = head[4]; int[] notes = ReadInts(); int[] pens = ReadInts(); // LINQ Select: 모든 공책이 남고 값만 바뀐다 int[] sale = notes.Select(p => p >= T ? p - d : p).ToArray(); // from 두 개는 적힌 차례대로 바깥 → 안쪽, where는 거르는 조건 var pairs = (from i in Enumerable.Range(0, n) from j in Enumerable.Range(0, m) where sale[i] + pens[j] <= B select (I: i + 1, J: j + 1, Total: sale[i] + pens[j])).ToList(); // Distinct로 같은 값을 하나로 모으고 OrderBy로 정렬한다 int[] totals = pairs.Select(p => p.Total).Distinct().OrderBy(t => t).ToArray(); var sb = new StringBuilder(); sb.Append(string.Join(" ", sale)).Append('\n'); sb.Append(pairs.Count).Append('\n'); foreach (var p in pairs) sb.Append($"{p.I} {p.J} {p.Total}\n"); sb.Append(totals.Length > 0 ? string.Join(" ", totals) : "-").Append('\n'); Console.Write(sb); }}
C++main.cpp · 48 行
#include <algorithm>#include <array>#include <iostream>#include <set>#include <vector>using namespace std;int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n, m, B, T, d; cin >> n >> m >> B >> T >> d; vector<int> notes(n), pens(m); for (int &p : notes) cin >> p; for (int &p : pens) cin >> p; // transform: 모든 공책이 남고 값만 바뀐다 vector<int> sale(n); transform(notes.begin(), notes.end(), sale.begin(), [&](int p) { return p >= T ? p - d : p; }); // 두 겹은 for문 두 개로 쓴다 vector<array<int, 3>> pairs; set<int> totals; // 같은 값은 하나만, 늘 정렬된 채로 for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { int t = sale[i] + pens[j]; if (t <= B) { pairs.push_back({i + 1, j + 1, t}); totals.insert(t); } } } for (int i = 0; i < n; i++) cout << (i ? " " : "") << sale[i]; cout << '\n' << pairs.size() << '\n'; for (const auto &p : pairs) cout << p[0] << ' ' << p[1] << ' ' << p[2] << '\n'; if (totals.empty()) { cout << "-\n"; } else { bool first = true; for (int t : totals) { cout << (first ? "" : " ") << t; first = false; } cout << '\n'; } return 0;}
Cmain.c · 52 行
#include <stdio.h>#include <stdlib.h>#define MAXN 60static int cmp_int(const void *a, const void *b) { int x = *(const int *)a, y = *(const int *)b; return (x > y) - (x < y);}int main(void) { int n, m, B, T, d; static int sale[MAXN], pens[MAXN]; static int pi[MAXN * MAXN], pj[MAXN * MAXN], pt[MAXN * MAXN], totals[MAXN * MAXN]; scanf("%d %d %d %d %d", &n, &m, &B, &T, &d); /* C에는 내포가 없다. 읽으면서 바로 값을 바꾼다 */ for (int i = 0; i < n; i++) { int p; scanf("%d", &p); sale[i] = p >= T ? p - d : p; } for (int j = 0; j < m; j++) scanf("%d", &pens[j]); int count = 0; for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { if (sale[i] + pens[j] <= B) { pi[count] = i + 1; pj[count] = j + 1; pt[count] = sale[i] + pens[j]; totals[count] = pt[count]; count++; } } } for (int i = 0; i < n; i++) printf(i ? " %d" : "%d", sale[i]); printf("\n%d\n", count); for (int k = 0; k < count; k++) printf("%d %d %d\n", pi[k], pj[k], pt[k]); if (count == 0) { printf("-\n"); return 0; } /* 정렬한 뒤, 바로 앞과 같은 값은 건너뛴다 */ qsort(totals, (size_t)count, sizeof(int), cmp_int); for (int k = 0; k < count; k++) { if (k > 0 && totals[k] == totals[k - 1]) continue; printf(k ? " %d" : "%d", totals[k]); } printf("\n"); return 0;}
Craykonmain.cray · 62 行
첫줄 = 控制台.读数字();n = 첫줄[0];m = 첫줄[1];B = 첫줄[2];T = 첫줄[3];d = 첫줄[4];notes = 控制台.读数字();pens = 控制台.读数字();// 크레이콘에는 내포가 없다. 빈 목록에 하나씩 넣는다sale = [];遍历 (p 在 notes){ 如果 (p >= T) { sale.添加(p - d); } 否则 { sale.添加(p); }}控制台.输出(sale);줄들 = [];totals = [];循环 (i = 0; i < n; i++){ 循环 (j = 0; j < m; j++) { t = sale[i] + pens[j]; 如果 (t <= B) { 줄들.添加(i + 1 + " " + (j + 1) + " " + t); totals.添加(t); } }}控制台.输出(줄들.数量);遍历 (줄 在 줄들){ 控制台.输出(줄);}如果 (totals.数量 == 0){ 控制台.输出("-");}否则{ // 정렬한 뒤, 바로 앞과 같은 값은 건너뛴다 totals.排序(); 고른것 = [totals[0]]; 循环 (k = 1; k < totals.数量; k++) { 如果 (totals[k] != totals[k - 1]) { 고른것.添加(totals[k]); } } 控制台.输出(고른것);}