A game character starts at level 1 with 0 experience points (XP).
The XP needed to reach the next level is called the threshold. The first threshold is a and the first increment is d.
q events happen in order, and each event gives one nonzero integer x.
If x is positive, the character gains XP. If this is the k-th event in an unbroken run of positive events, add x + (k − 1) × b to the XP. k = 1 if this is the first event or the previous event was a penalty; if the previous event was positive, k is one more than that event's k.
If x is negative, it is a penalty. Subtract −x from the XP, and if the result is below 0, set the XP to 0. A penalty breaks the run, so the next positive event is the 1st again.
After changing the XP for an event, repeat the following while the level is below M and the XP is at least the threshold: subtract the threshold from the XP, raise the level by 1, add the increment to the threshold, and then add g to the increment.
So one event can raise several levels, and the leftover XP carries over.
The level never goes down. Once the level is M it stops rising, and XP keeps piling up without being subtracted.
The first line gives a, d, g, M and b separated by single spaces, the second line gives q, and each of the next q lines gives one x.
For each event print the level and the XP after handling that event, separated by one space, on one line.
On the last line print the largest number of levels gained in a single event (0 if the level never rose).
Input
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. All are integers, given as plain digits without commas
Output
q + 1 lines. The level and XP for each event, then the largest number of levels gained in one event. Write numbers as plain digits without commas
Example 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
Error List00F8 ↓ · ⇧F8 ↑
Input (stdin)
When you run, these lines are fed to input()/stdin in order (the program doesn't stop to ask).
$ Ready
Open this on a computer to write and run code. On mobile you can read the problem and the solutions.
In other languagesShow solutions by language · 8 languages
Five variables keep building on their value from the previous pass of the loop (XP, threshold, increment, run length, best gain). += as in xp += x exists in all eight languages; only Python has no level++ (write level += 1). Trap 1: one event can raise several levels, so use while (Craykon while), not if, to repeat 'while the XP is at least the threshold'. With if, the second event of the example stops at level 3. Trap 2: after adding the increment to the threshold you must also add g to the increment. One accumulator feeds another, so that line is easy to forget. Trap 3: writing > instead of >= fails to level up when the XP equals the threshold exactly. Trap 4: at the top level the loop must stop with level < M. Without it the level rises past M. Trap 5: a penalty must not push the XP below 0: Python max(0, v), JS, TS and Java Math.max(0, v), C# Math.Max(0, v), C++ std::max(0LL, v) (both arguments must have the same type, so 0LL, not 0), Craykon Mathf.Max(0, v). The C standard library has no max function for integers, so write if (xp < 0) xp = 0;. Trap 6: a penalty must reset the run length to 0, and the bonus of the k-th event in a run is (k − 1) × b, not k × b. Trap 7: the XP grows to about 1.5 trillion and the threshold can also pass 2.1 billion, so neither fits in an int (about 2.1 billion). Use long long in C and C++ (%lld in printf) and long in Java and C#. Python integers have no size limit, and numbers in JS, TS and Craykon are exact up to 2^53 (about 9 × 10^15), so they work as they are.
Pythonmain.py · 31 lines
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 lines
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 lines
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 lines
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 lines
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 lines
#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 lines
#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 lines
p = Console.ReadNumbers();a = p[0];d = p[1];g = p[2];M = p[3];b = p[4];q = Console.ReadLine().ToNumber();level = 1;xp = 0;need = a; // 문턱step = d; // 증가폭: 오를 때마다 문턱과 함께 쌓인다streak = 0; // 연달아 얻은 횟수best = 0; // 한 사건에서 가장 많이 오른 레벨 수for (i = 0; i < q; i++){ x = Console.ReadLine().ToNumber(); if (x > 0) { streak += 1; xp += x + (streak - 1) * b; } else { streak = 0; xp = Mathf.Max(0, xp + x); } ups = 0; // 한 번에 여러 레벨을 오를 수 있으니 만약이 아니라 동안 while (level < M && xp >= need) { xp -= need; level += 1; need += step; step += g; ups += 1; } best = Mathf.Max(best, ups); Console.WriteLine(level + " " + xp);}Console.WriteLine(best);