游戏角色从等级 1、经验值 0 开始。 升到下一级所需的经验值叫做门槛。 最初的门槛是 a,最初的增幅是 d。 q 个事件依次发生,每个事件给出一个不为 0 的整数 x。 x 为正时获得经验值。 如果这个事件是没有中断的连续正数事件中的第 k 个,就给经验值加上 x + (k − 1) × b。 它是第一个事件或者上一个事件是罚分时 k = 1;上一个事件是正数时,k 比那个事件的 k 大 1。 x 为负时是罚分。 从经验值中减去 −x,结果小于 0 时把经验值设为 0。 罚分会打断连续,所以下一个正数事件重新算第 1 次。 每个事件改完经验值之后,只要等级小于 M 且经验值不小于门槛,就重复下面的步骤:经验值减去门槛,等级加 1,门槛加上增幅,然后增幅加上 g。 所以一个事件可以连升几级,剩下的经验值留到下一次。 等级不会下降。 等级到 M 之后不再上升,经验值不再扣减,只会继续累积。 第一行给出 a、d、g、M、b,用一个空格隔开;第二行给出 q;接下来 q 行每行给出一个 x。 对每个事件,在一行中输出处理完该事件后的等级和经验值,用一个空格隔开。 最后一行输出单个事件中升级数的最大值(一次也没升过则为 0)。
输入
1 ≤ a ≤ 1,000,000,000,0 ≤ d ≤ 1,000,000,0 ≤ g ≤ 1,000,1 ≤ M ≤ 10,000,0 ≤ b ≤ 1,000,000,1 ≤ q ≤ 1,000,1 ≤ |x| ≤ 1,000,000,000。 全部是整数,只给出数字,不带逗号
输出
q + 1 行。 每个事件的等级和经验值,最后一行是单个事件中升得最多的级数。 数字不带逗号
样例 1 · stdin
10 5 2 5 3
6
12
60
-25
50
7
100
stdout
2 2
4 28
4 3
5 22
5 32
5 138
2
main.py
错误列表00F8 ↓ · ⇧F8 ↑
输入(stdin)
运行时这些行会依次作为 input()/标准输入传入(运行中不会等待输入)。
$ 就绪
请在电脑上打开以编写和运行代码。在手机上可以查看题目和题解。
其他语言怎么写?查看各语言题解 · 8 种语言题解
循环每转一圈都接着上一圈的值继续累加的变量有五个(经验值、门槛、增幅、连续次数、最多升级数)。 xp += x 这样的 += 八种语言都有,只有 Python 没有 level++(写 level += 1)。 陷阱 ① 一个事件可能连升几级,所以要用 while(Craykon 当)而不是 if,在“经验值不小于门槛期间”重复。 用 if 的话,示例的第二个事件会停在等级 3。 ② 门槛加上增幅之后,增幅也要加上 g。 一个累加量叠在另一个累加量上,很容易漏掉一行。 ③ 把 >= 写成 >,经验值正好等于门槛时就升不了级。 ④ 到最高等级时要用 level < M 停下,否则会升过 M。 ⑤ 罚分不能让经验值低于 0:Python max(0, v),JS・TS・Java Math.max(0, v),C# Math.Max(0, v),C++ std::max(0LL, v)(两个参数类型必须相同,所以是 0LL 而不是 0),Craykon 数学.较大值(0, v)。 C 标准库没有整数用的 max 函数,所以写 if (xp < 0) xp = 0;。 ⑥ 出现罚分时要把连续次数清零,连续第 k 次的奖励是 (k − 1) × b 而不是 k × b。 ⑦ 经验值会涨到约 1.5 万亿,门槛也可能超过 21 亿,int(约 21 亿)装不下。 C・C++ 用 long long(printf 用 %lld),Java・C# 用 long。 Python 的整数没有大小限制,JS・TS・Craykon 的数在 2^53(约 9 × 10^15)以内整数是精确的,所以可以直接用。
Pythonmain.py · 31 行
import syslines = sys.stdin.read().split("\n")a, d, g, M, b = map(int, lines[0].split())q = int(lines[1])level, xp = 1, 0need, step = a, d # 문턱과 증가폭: 오를 때마다 둘 다 쌓인다streak = 0 # 연달아 얻은 횟수best = 0 # 한 사건에서 가장 많이 오른 레벨 수out = []for i in range(q): x = int(lines[2 + i]) if x > 0: streak += 1 xp += x + (streak - 1) * b else: streak = 0 xp = max(0, xp + x) ups = 0 # 한 번에 여러 레벨을 오를 수 있으니 if가 아니라 while while level < M and xp >= need: xp -= need level += 1 need += step step += g ups += 1 best = max(best, ups) out.append(f"{level} {xp}")out.append(str(best))print("\n".join(out))
JavaScriptmain.js · 32 行
const lines = require("fs").readFileSync(0, "utf8").split("\n");const [a, d, g, M, b] = lines[0].trim().split(/\s+/).map(Number);const q = Number(lines[1]);let level = 1, xp = 0;let need = a, step = d; // 문턱과 증가폭: 오를 때마다 둘 다 쌓인다let streak = 0; // 연달아 얻은 횟수let best = 0; // 한 사건에서 가장 많이 오른 레벨 수const out = [];for (let i = 0; i < q; i++) { const x = Number(lines[2 + i]); if (x > 0) { streak += 1; xp += x + (streak - 1) * b; } else { streak = 0; xp = Math.max(0, xp + x); } let ups = 0; // 한 번에 여러 레벨을 오를 수 있으니 if가 아니라 while while (level < M && xp >= need) { xp -= need; level += 1; need += step; step += g; ups += 1; } best = Math.max(best, ups); out.push(`${level} ${xp}`);}out.push(String(best));console.log(out.join("\n"));
TypeScriptmain.ts · 34 行
import { readFileSync } from "node:fs";const lines: string[] = readFileSync(0, "utf8").split("\n");const [a, d, g, M, b]: number[] = lines[0].trim().split(/\s+/).map(Number);const q = Number(lines[1]);let level = 1, xp = 0;let need = a, step = d; // 문턱과 증가폭: 오를 때마다 둘 다 쌓인다let streak = 0; // 연달아 얻은 횟수let best = 0; // 한 사건에서 가장 많이 오른 레벨 수const out: string[] = [];for (let i = 0; i < q; i++) { const x = Number(lines[2 + i]); if (x > 0) { streak += 1; xp += x + (streak - 1) * b; } else { streak = 0; xp = Math.max(0, xp + x); } let ups = 0; // 한 번에 여러 레벨을 오를 수 있으니 if가 아니라 while while (level < M && xp >= need) { xp -= need; level += 1; need += step; step += g; ups += 1; } best = Math.max(best, ups); out.push(`${level} ${xp}`);}out.push(String(best));console.log(out.join("\n"));
JavaMain.java · 41 行
import java.util.Scanner;public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); long a = sc.nextLong(), d = sc.nextLong(), g = sc.nextLong(); int M = sc.nextInt(); long b = sc.nextLong(); int q = sc.nextInt(); int level = 1; long xp = 0; // 1조 넘게 쌓여서 int로는 모자란다 long need = a, step = d; // 문턱과 증가폭: 오를 때마다 둘 다 쌓인다 long streak = 0; // 연달아 얻은 횟수 int best = 0; // 한 사건에서 가장 많이 오른 레벨 수 StringBuilder out = new StringBuilder(); for (int i = 0; i < q; i++) { long x = sc.nextLong(); if (x > 0) { streak += 1; xp += x + (streak - 1) * b; } else { streak = 0; xp = Math.max(0, xp + x); } int ups = 0; // 한 번에 여러 레벨을 오를 수 있으니 if가 아니라 while while (level < M && xp >= need) { xp -= need; level += 1; need += step; step += g; ups += 1; } best = Math.max(best, ups); out.append(level).append(' ').append(xp).append('\n'); } out.append(best).append('\n'); System.out.print(out); }}
C#Main.cs · 49 行
using System;using System.Text;class Program{ static void Main() { string[] p = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries); long a = long.Parse(p[0]), d = long.Parse(p[1]), g = long.Parse(p[2]); int M = int.Parse(p[3]); long b = long.Parse(p[4]); int q = int.Parse(Console.ReadLine().Trim()); int level = 1; long xp = 0; // 1조 넘게 쌓여서 int로는 모자란다 long need = a, step = d; // 문턱과 증가폭: 오를 때마다 둘 다 쌓인다 long streak = 0; // 연달아 얻은 횟수 int best = 0; // 한 사건에서 가장 많이 오른 레벨 수 var output = new StringBuilder(); for (int i = 0; i < q; i++) { long x = long.Parse(Console.ReadLine().Trim()); if (x > 0) { streak += 1; xp += x + (streak - 1) * b; } else { streak = 0; xp = Math.Max(0, xp + x); } int ups = 0; // 한 번에 여러 레벨을 오를 수 있으니 if가 아니라 while while (level < M && xp >= need) { xp -= need; level += 1; need += step; step += g; ups += 1; } best = Math.Max(best, ups); output.Append(level).Append(' ').Append(xp).Append('\n'); } output.Append(best).Append('\n'); Console.Write(output); }}
C++main.cpp · 38 行
#include <algorithm>#include <iostream>int main() { std::ios::sync_with_stdio(false); long long a, d, g, b; int M, q; std::cin >> a >> d >> g >> M >> b >> q; int level = 1; long long xp = 0; // 1조 넘게 쌓여서 int로는 모자란다 long long need = a, step = d; // 문턱과 증가폭: 오를 때마다 둘 다 쌓인다 long long streak = 0; // 연달아 얻은 횟수 int best = 0; // 한 사건에서 가장 많이 오른 레벨 수 for (int i = 0; i < q; i++) { long long x; std::cin >> x; if (x > 0) { streak += 1; xp += x + (streak - 1) * b; } else { streak = 0; xp = std::max(0LL, xp + x); // 두 인수의 타입이 같아야 해서 0LL } int ups = 0; // 한 번에 여러 레벨을 오를 수 있으니 if가 아니라 while while (level < M && xp >= need) { xp -= need; level += 1; need += step; step += g; ups += 1; } best = std::max(best, ups); std::cout << level << ' ' << xp << '\n'; } std::cout << best << '\n';}
Cmain.c · 38 行
#include <stdio.h>int main(void) { long long a, d, g, b; int M, q; scanf("%lld %lld %lld %d %lld %d", &a, &d, &g, &M, &b, &q); int level = 1; long long xp = 0; /* 1조 넘게 쌓여서 int로는 모자란다 */ long long need = a, step = d; /* 문턱과 증가폭: 오를 때마다 둘 다 쌓인다 */ long long streak = 0; /* 연달아 얻은 횟수 */ int best = 0; /* 한 사건에서 가장 많이 오른 레벨 수 */ for (int i = 0; i < q; i++) { long long x; scanf("%lld", &x); if (x > 0) { streak += 1; xp += x + (streak - 1) * b; } else { streak = 0; xp += x; if (xp < 0) xp = 0; } int ups = 0; /* 한 번에 여러 레벨을 오를 수 있으니 if가 아니라 while */ while (level < M && xp >= need) { xp -= need; level += 1; need += step; step += g; ups += 1; } if (ups > best) best = ups; printf("%d %lld\n", level, xp); } printf("%d\n", best); return 0;}
Craykonmain.cray · 41 行
p = 控制台.读数字();a = p[0];d = p[1];g = p[2];M = p[3];b = p[4];q = 控制台.读行().转数字();level = 1;xp = 0;need = a; // 문턱step = d; // 증가폭: 오를 때마다 문턱과 함께 쌓인다streak = 0; // 연달아 얻은 횟수best = 0; // 한 사건에서 가장 많이 오른 레벨 수循环 (i = 0; i < q; i++){ x = 控制台.读行().转数字(); 如果 (x > 0) { streak += 1; xp += x + (streak - 1) * b; } 否则 { streak = 0; xp = 数学.较大值(0, xp + x); } ups = 0; // 한 번에 여러 레벨을 오를 수 있으니 만약이 아니라 동안 当 (level < M && xp >= need) { xp -= need; level += 1; need += step; step += g; ups += 1; } best = 数学.较大值(best, ups); 控制台.输出(level + " " + xp);}控制台.输出(best);