{ }codelper
sum64-bit integerssplitting stringsP0268

Checking a receipt with subtotals

Receipts at a wholesale market have subtotal lines and total lines written between the lines for the goods bought. Some of the written subtotals and totals are wrong, so you want to check them. The first line gives the number of receipt lines n, and the next n lines give the receipt from the top, one line each. Each line is one of the following three kinds, with words and numbers separated by single spaces. "ITEM p q" means q pieces of an item costing p won each were bought, and the amount of this line is p × q won. "SUB s" is a subtotal line.
It claims that the amounts of all ITEM lines after the previous SUB line (from the top of the receipt if there is no earlier SUB line) up to this line add up to s won. "TOTAL s" is a total line.
It claims that the amounts of all ITEM lines from the top of the receipt up to this line add up to s won. A TOTAL line does not break the section counted by a subtotal. The numbers written on SUB and TOTAL lines are not amounts, so they are never added to any sum. The last line of the receipt is always a TOTAL line. For each SUB and TOTAL line, print one line, from the top. Print "OK" if the written value equals the real sum; otherwise print "FIX" and the real sum separated by one space. Write the real sum as plain digits, with no commas.

Input
1 ≤ n ≤ 10,000, 1 ≤ p ≤ 10,000,000, 1 ≤ q ≤ 1,000, 0 ≤ s ≤ 10^15 (all integers, no leading zeros)
Output
One line per SUB/TOTAL line: OK, or FIX and the real sum
Example 1 · stdin
6
ITEM 1200 3
ITEM 500 2
SUB 4600
ITEM 9900 1
SUB 9000
TOTAL 14500
stdout
OK
FIX 9900
OK
Example 2 · stdin
4
SUB 0
ITEM 10000000 1000
SUB 10000000000
TOTAL 1410065408
stdout
OK
OK
FIX 10000000000
main.py
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

Keep two sums, add to both on every ITEM line, and reset only the subtotal to 0 on a SUB line.
The first trap is size.
One line's amount reaches 10^10 and the sum reaches 10^14, so C/C++ need long long and Java/C# need long.
Making only the sums long and multiplying int p, q overflows int at the moment of multiplying (1410065408 in example 2 is 10^10 after overflowing).
Convert one side to long before multiplying.
Python's int never overflows, and numbers in JS, TS and Craykon are exact up to 2^53 (about 9×10^15), so 10^14 is fine.
The second trap is that the pieces of a split line are strings.
Convert them with Python int(...), JS/TS Number(...), Java Long.parseLong, C# long.Parse or Craykon .ToNumber().
In JS/TS "5" === 5 is false, so comparing without converting turns every line into FIX, and Craykon stops if you try to multiply strings.
Comparing the words differs too.
Java uses kind.equals("ITEM") (== asks whether it is the same object), C uses strcmp(kind, "ITEM") == 0, and the others work with == (JS/TS ===).
In C, scanf("%7s", kind) reads the word and the numbers in one go.
Third, adding the written subtotal into the total, or resetting the subtotal on a TOTAL line, throws off every later check.

Pythonmain.py · 14 lines
n = int(input())sub = 0    # 지난 SUB 뒤로 산 물건값의 합total = 0  # 처음부터 산 물건값의 합for _ in range(n):    kind, *nums = input().split()    if kind == "ITEM":        amount = int(nums[0]) * int(nums[1])        sub += amount        total += amount    else:        actual = sub if kind == "SUB" else total        print("OK" if int(nums[0]) == actual else f"FIX {actual}")        if kind == "SUB":            sub = 0  # 소계는 구역마다 다시 센다. TOTAL은 구역을 끊지 않는다
JavaScriptmain.js · 18 lines
const lines = require("fs").readFileSync(0, "utf8").split("\n");const n = Number(lines[0]);// 합계는 10^14까지: 2^53(약 9×10^15) 안이라 Number로 정확하다let sub = 0, total = 0;const out = [];for (let i = 1; i <= n; i++) {  const [kind, a, b] = lines[i].trim().split(/\s+/);  if (kind === "ITEM") {    const amount = Number(a) * Number(b);    sub += amount;    total += amount;  } else {    const actual = kind === "SUB" ? sub : total;    out.push(Number(a) === actual ? "OK" : `FIX ${actual}`); // 문자열 a와 수를 ===로 견주면 늘 false    if (kind === "SUB") sub = 0;  }}console.log(out.join("\n"));
TypeScriptmain.ts · 19 lines
import { readFileSync } from "node:fs";const lines: string[] = readFileSync(0, "utf8").split("\n");const n: number = Number(lines[0]);// 합계는 10^14까지: 2^53(약 9×10^15) 안이라 number로 정확하다let sub = 0, total = 0;const out: string[] = [];for (let i = 1; i <= n; i++) {  const [kind, a, b] = lines[i].trim().split(/\s+/);  if (kind === "ITEM") {    const amount: number = Number(a) * Number(b);    sub += amount;    total += amount;  } else {    const actual: number = kind === "SUB" ? sub : total;    out.push(Number(a) === actual ? "OK" : `FIX ${actual}`);    if (kind === "SUB") sub = 0;  }}console.log(out.join("\n"));
JavaMain.java · 29 lines
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.util.StringTokenizer; public class Main {    public static void main(String[] args) throws IOException {        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));        int n = Integer.parseInt(in.readLine().trim());        long sub = 0, total = 0; // 합계는 10^14까지: int로는 넘친다        StringBuilder out = new StringBuilder();        for (int i = 0; i < n; i++) {            StringTokenizer st = new StringTokenizer(in.readLine());            String kind = st.nextToken();            if (kind.equals("ITEM")) { // 문자열은 ==가 아니라 equals로 견준다                // 값 × 개수도 10^10까지: 곱하기 전에 long으로                long amount = Long.parseLong(st.nextToken()) * Long.parseLong(st.nextToken());                sub += amount;                total += amount;            } else {                long actual = kind.equals("SUB") ? sub : total;                long claim = Long.parseLong(st.nextToken());                out.append(claim == actual ? "OK" : "FIX " + actual).append('\n');                if (kind.equals("SUB")) sub = 0;            }        }        System.out.print(out);    }}
C#Main.cs · 30 lines
using System;using System.Text; class Program{    static void Main()    {        int n = int.Parse(Console.ReadLine());        long sub = 0, total = 0; // 합계는 10^14까지: int로는 넘친다        var out_ = new StringBuilder();        for (int i = 0; i < n; i++)        {            string[] p = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries);            if (p[0] == "ITEM")            {                // 값 × 개수도 10^10까지: 곱하기 전에 long으로                long amount = long.Parse(p[1]) * long.Parse(p[2]);                sub += amount;                total += amount;            }            else            {                long actual = p[0] == "SUB" ? sub : total;                out_.Append(long.Parse(p[1]) == actual ? "OK" : "FIX " + actual).Append('\n');                if (p[0] == "SUB") sub = 0;            }        }        Console.Write(out_);    }}
C++main.cpp · 26 lines
#include <iostream>#include <string> int main() {    std::ios::sync_with_stdio(false);    int n;    std::cin >> n;    long long sub = 0, total = 0; // 합계는 10^14까지: int로는 넘친다    for (int i = 0; i < n; i++) {        std::string kind;        std::cin >> kind;        if (kind == "ITEM") {            long long p, q; // 값 × 개수도 10^10까지            std::cin >> p >> q;            sub += p * q;            total += p * q;        } else {            long long claim;            std::cin >> claim;            long long actual = kind == "SUB" ? sub : total;            if (claim == actual) std::cout << "OK\n";            else std::cout << "FIX " << actual << '\n';            if (kind == "SUB") sub = 0;        }    }}
Cmain.c · 27 lines
#include <stdio.h>#include <string.h> int main(void) {    int n;    scanf("%d", &n);    long long sub = 0, total = 0; /* 합계는 10^14까지: int로는 넘친다 */    for (int i = 0; i < n; i++) {        char kind[8];        scanf("%7s", kind);        if (strcmp(kind, "ITEM") == 0) { /* 문자열은 ==가 아니라 strcmp로 견준다 */            long long p, q; /* 값 × 개수도 10^10까지 */            scanf("%lld %lld", &p, &q);            sub += p * q;            total += p * q;        } else {            long long claim;            scanf("%lld", &claim);            int is_sub = strcmp(kind, "SUB") == 0;            long long actual = is_sub ? sub : total;            if (claim == actual) puts("OK");            else printf("FIX %lld\n", actual);            if (is_sub) sub = 0;        }    }    return 0;}
Craykonmain.cray · 34 lines
n = Console.ReadLine().ToNumber();sub = 0; // 지난 SUB 뒤로 산 물건값의 합total = 0; // 처음부터 산 물건값의 합(10^14까지: 2^53 안이라 정확하다)for (i = 0; i < n; i++){    p = Console.ReadLine().Split();    if (p[0] == "ITEM")    {        // 나눈 조각은 문자열이다: 수로 바꾼 다음 곱한다        amount = p[1].ToNumber() * p[2].ToNumber();        sub += amount;        total += amount;    }    else    {        actual = total;        if (p[0] == "SUB")        {            actual = sub;        }        if (p[1].ToNumber() == actual)        {            Console.WriteLine("OK");        }        else        {            Console.WriteLine("FIX " + actual);        }        if (p[0] == "SUB")        {            sub = 0;        }    }}