{ }codelper
쌓아 가기조건문큰 정수(64비트)P0137

누진 세율로 소득세 계산

사람마다 한 해 소득과 공제 인원 k가 주어진다. 과세표준은 소득에서 1,500,000 × k를 뺀 값이고, 0보다 작으면 0으로 한다. 세금은 과세표준을 아래 구간으로 나누어, 구간에 든 부분마다 그 구간의 세율을 곱해 모두 더한다. 14,000,000원 이하인 부분은 6%이다. 14,000,000원 초과 50,000,000원 이하인 부분은 15%이다. 50,000,000원 초과 88,000,000원 이하인 부분은 24%이다. 88,000,000원 초과 150,000,000원 이하인 부분은 35%이다. 150,000,000원 초과 300,000,000원 이하인 부분은 38%이다. 300,000,000원 초과 500,000,000원 이하인 부분은 40%이다. 500,000,000원 초과 1,000,000,000원 이하인 부분은 42%이다. 1,000,000,000원을 넘는 부분은 45%이다. 이렇게 더한 값을 원 단위로 내림한 것이 산출세액 T이다(구간마다 내림하지 않고, 모두 더한 뒤 한 번만 내림한다). 다음으로 세액공제 C를 정한다. T가 1,300,000 이하이면 C는 T × 55 / 100을 내림한 값이다. T가 1,300,000을 넘으면 C는 715,000에 (T − 1,300,000) × 30 / 100을 내림한 값을 더한 것인데, 740,000을 넘으면 740,000으로 한다. 낼 세액은 T − C이다. 한계세율은 과세표준의 마지막 1원이 든 구간의 세율(%)이고, 과세표준이 0이면 0이다. 과세표준이 구간의 위 끝과 같으면 그 구간에 든 것으로 본다. 첫 줄에 사람 수 n이 주어지고, 다음 n줄에 사람마다 소득과 k가 빈칸 하나를 사이에 두고 주어진다. 사람마다 한 줄에 T, 낼 세액, 한계세율(% 기호 없이 수만)을 빈칸 하나씩 띄워 입력 차례대로 출력하라.

입력
1 ≤ n ≤ 1,000, 0 ≤ 소득 ≤ 100,000,000,000, 1 ≤ k ≤ 20, 모두 정수
출력
n줄, 줄마다 정수 세 개: 산출세액, 낼 세액, 한계세율
예시 1 · stdin
3
60000000 3
15500000 1
3000000 2
stdout
7560000 6820000 24
840000 378000 6
0 0 0
main.py
입력(stdin)

실행하면 이 줄들이 차례로 input()·표준 입력으로 들어가요(실행 중에 묻지 않아요).

$ 준비됐어요

코드를 입력해 풀려면 PC에서 열어 주세요. 모바일에서는 문제와 풀이를 볼 수 있어요.

다른 언어로는?언어별 풀이 보기 · 8개 언어 풀이

누진세는 '구간을 차례로 돌며 그 구간에 든 만큼만 쌓아 가는' 반복이에요.
if (base <= low) break;로 과세표준이 구간 아래 끝을 넘지 못하면 멈추고, 넘으면 min(base, high) - low만큼에 세율을 곱해 더해요.
과세표준 전체에 마지막 구간의 세율을 곱하는 것이 가장 흔한 실수예요(예시의 55,500,000원이면 13,320,000원이 나와요).
<= 대신 <로 멈추면 과세표준이 딱 14,000,000원일 때 한계세율이 15로 바뀌어요.
쌓는 값은 최대 약 4.5조라 int(약 21억)에 담기지 않아요: C·C++ long long(printf는 %lld), Java·C# long, 리터럴도 1_500_000L * k처럼 long으로 곱해요.
Python은 정수 크기에 제한이 없고, JS·TS·크레이콘은 수가 하나(double)지만 2^53(약 9 × 10^15) 안이라 정확해요.
세율을 0.35 같은 실수로 곱해 버리면 이진 실수 오차 때문에 1원이 모자랄 수 있어요: 180 * 0.35는 63이 아니라 62.99999999999999라서, 과세표준 88,000,180원의 35% 부분을 구간마다 버리면 62원이 돼요.
그래서 퍼센트 정수를 곱해 쌓고 100으로는 맨 마지막에 정수 나눗셈으로 한 번만 나눠요: Python //, C 계열 정수 /, JS·TS Math.floor(a / 100), 크레이콘 수학.몫(a, 100).
공제는 두 갈래 if-else예요: Python if … else:, 크레이콘 만약 … 아니면.
한도 740,000원은 min으로 한 번 더 눌러요.

Pythonmain.py · 37 줄
import sys # (구간 아래 끝, 위 끝, 세율 %) — 아래 끝 초과 위 끝 이하인 부분에 그 세율BRACKETS = [    (0, 14_000_000, 6),    (14_000_000, 50_000_000, 15),    (50_000_000, 88_000_000, 24),    (88_000_000, 150_000_000, 35),    (150_000_000, 300_000_000, 38),    (300_000_000, 500_000_000, 40),    (500_000_000, 1_000_000_000, 42),    (1_000_000_000, 10**18, 45),] data = sys.stdin.read().split()n = int(data[0])out = []for i in range(n):    income = int(data[1 + 2 * i])    k = int(data[2 + 2 * i])    base = max(income - 1_500_000 * k, 0)     total = 0  # 세율을 곱한 값을 쌓는다(100으로는 마지막에 한 번 나눈다)    rate = 0    for low, high, r in BRACKETS:        if base <= low:            break        total += (min(base, high) - low) * r        rate = r    tax = total // 100     if tax <= 1_300_000:        credit = tax * 55 // 100    else:        credit = min(715_000 + (tax - 1_300_000) * 30 // 100, 740_000)    out.append(f"{tax} {tax - credit} {rate}")print("\n".join(out))
JavaScriptmain.js · 39 줄
const data = require("fs").readFileSync(0, "utf8").trim().split(/\s+/).map(Number); // [구간 아래 끝, 위 끝, 세율 %] — 아래 끝 초과 위 끝 이하인 부분에 그 세율const BRACKETS = [  [0, 14000000, 6],  [14000000, 50000000, 15],  [50000000, 88000000, 24],  [88000000, 150000000, 35],  [150000000, 300000000, 38],  [300000000, 500000000, 40],  [500000000, 1000000000, 42],  [1000000000, Infinity, 45],]; const n = data[0];const out = [];for (let i = 0; i < n; i++) {  const income = data[1 + 2 * i];  const k = data[2 + 2 * i];  const base = Math.max(income - 1500000 * k, 0);   let total = 0; // 세율을 곱한 값을 쌓는다(최대 약 4.5조라 2^53 안에서 정확)  let rate = 0;  for (const [low, high, r] of BRACKETS) {    if (base <= low) break;    total += (Math.min(base, high) - low) * r;    rate = r;  }  const tax = Math.floor(total / 100);   let credit;  if (tax <= 1300000) {    credit = Math.floor((tax * 55) / 100);  } else {    credit = Math.min(715000 + Math.floor(((tax - 1300000) * 30) / 100), 740000);  }  out.push(`${tax} ${tax - credit} ${rate}`);}console.log(out.join("\n"));
TypeScriptmain.ts · 40 줄
import { readFileSync } from "node:fs";const data: number[] = readFileSync(0, "utf8").trim().split(/\s+/).map(Number); // [구간 아래 끝, 위 끝, 세율 %] — 아래 끝 초과 위 끝 이하인 부분에 그 세율const BRACKETS: [number, number, number][] = [  [0, 14000000, 6],  [14000000, 50000000, 15],  [50000000, 88000000, 24],  [88000000, 150000000, 35],  [150000000, 300000000, 38],  [300000000, 500000000, 40],  [500000000, 1000000000, 42],  [1000000000, Infinity, 45],]; const n: number = data[0];const out: string[] = [];for (let i = 0; i < n; i++) {  const income: number = data[1 + 2 * i];  const k: number = data[2 + 2 * i];  const base: number = Math.max(income - 1500000 * k, 0);   let total = 0; // 세율을 곱한 값을 쌓는다(최대 약 4.5조라 2^53 안에서 정확)  let rate = 0;  for (const [low, high, r] of BRACKETS) {    if (base <= low) break;    total += (Math.min(base, high) - low) * r;    rate = r;  }  const tax: number = Math.floor(total / 100);   let credit: number;  if (tax <= 1300000) {    credit = Math.floor((tax * 55) / 100);  } else {    credit = Math.min(715000 + Math.floor(((tax - 1300000) * 30) / 100), 740000);  }  out.push(`${tax} ${tax - credit} ${rate}`);}console.log(out.join("\n"));
JavaMain.java · 41 줄
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.util.StringTokenizer; public class Main {    // 구간 아래 끝과 세율 % — 아래 끝 초과 다음 아래 끝 이하인 부분에 그 세율    static final long[] LOW = {0L, 14_000_000L, 50_000_000L, 88_000_000L, 150_000_000L, 300_000_000L, 500_000_000L, 1_000_000_000L};    static final int[] RATE = {6, 15, 24, 35, 38, 40, 42, 45};     public static void main(String[] args) throws IOException {        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));        int n = Integer.parseInt(br.readLine().trim());        StringBuilder out = new StringBuilder();        for (int i = 0; i < n; i++) {            StringTokenizer st = new StringTokenizer(br.readLine());            long income = Long.parseLong(st.nextToken());            int k = Integer.parseInt(st.nextToken());            long base = Math.max(income - 1_500_000L * k, 0L);             long total = 0; // 세율을 곱한 값을 쌓는다(최대 약 4.5조라 int로는 넘친다)            int rate = 0;            for (int b = 0; b < LOW.length; b++) {                if (base <= LOW[b]) break;                long high = b + 1 < LOW.length ? LOW[b + 1] : Long.MAX_VALUE;                total += (Math.min(base, high) - LOW[b]) * RATE[b];                rate = RATE[b];            }            long tax = total / 100;             long credit;            if (tax <= 1_300_000) {                credit = tax * 55 / 100;            } else {                credit = Math.min(715_000 + (tax - 1_300_000) * 30 / 100, 740_000);            }            out.append(tax).append(' ').append(tax - credit).append(' ').append(rate).append('\n');        }        System.out.print(out);    }}
C#Main.cs · 45 줄
using System;using System.Text; class Program{    // 구간 아래 끝과 세율 % — 아래 끝 초과 다음 아래 끝 이하인 부분에 그 세율    static readonly long[] Low = { 0L, 14_000_000L, 50_000_000L, 88_000_000L, 150_000_000L, 300_000_000L, 500_000_000L, 1_000_000_000L };    static readonly int[] Rate = { 6, 15, 24, 35, 38, 40, 42, 45 };     static void Main()    {        int n = int.Parse(Console.ReadLine().Trim());        var sb = new StringBuilder();        for (int i = 0; i < n; i++)        {            string[] p = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries);            long income = long.Parse(p[0]);            int k = int.Parse(p[1]);            long baseAmount = Math.Max(income - 1_500_000L * k, 0L);             long total = 0; // 세율을 곱한 값을 쌓는다(최대 약 4.5조라 int로는 넘친다)            int rate = 0;            for (int b = 0; b < Low.Length; b++)            {                if (baseAmount <= Low[b]) break;                long high = b + 1 < Low.Length ? Low[b + 1] : long.MaxValue;                total += (Math.Min(baseAmount, high) - Low[b]) * Rate[b];                rate = Rate[b];            }            long tax = total / 100;             long credit;            if (tax <= 1_300_000)            {                credit = tax * 55 / 100;            }            else            {                credit = Math.Min(715_000 + (tax - 1_300_000) * 30 / 100, 740_000);            }            sb.Append(tax).Append(' ').Append(tax - credit).Append(' ').Append(rate).Append('\n');        }        Console.Write(sb);    }}
C++main.cpp · 36 줄
#include <algorithm>#include <array>#include <iostream>#include <limits> int main() {    // 구간 아래 끝과 세율 % — 아래 끝 초과 다음 아래 끝 이하인 부분에 그 세율    const std::array<long long, 8> low = {0LL, 14000000LL, 50000000LL, 88000000LL, 150000000LL, 300000000LL, 500000000LL, 1000000000LL};    const std::array<int, 8> rates = {6, 15, 24, 35, 38, 40, 42, 45};    int n;    std::cin >> n;    for (int i = 0; i < n; i++) {        long long income;        int k;        std::cin >> income >> k;        long long base = std::max(income - 1500000LL * k, 0LL);         long long total = 0; // 세율을 곱한 값을 쌓는다(최대 약 4.5조라 int로는 넘친다)        int rate = 0;        for (int b = 0; b < 8; b++) {            if (base <= low[b]) break;            long long high = b + 1 < 8 ? low[b + 1] : std::numeric_limits<long long>::max();            total += (std::min(base, high) - low[b]) * rates[b];            rate = rates[b];        }        long long tax = total / 100;         long long credit;        if (tax <= 1300000) {            credit = tax * 55 / 100;        } else {            credit = std::min(715000 + (tax - 1300000) * 30 / 100, 740000LL);        }        std::cout << tax << ' ' << tax - credit << ' ' << rate << '\n';    }}
Cmain.c · 38 줄
#include <stdio.h> /* 구간 아래 끝과 세율 % — 아래 끝 초과 다음 아래 끝 이하인 부분에 그 세율 */static const long long LOW[8] = {0LL, 14000000LL, 50000000LL, 88000000LL, 150000000LL, 300000000LL, 500000000LL, 1000000000LL};static const int RATE[8] = {6, 15, 24, 35, 38, 40, 42, 45}; int main(void) {    int n;    scanf("%d", &n);    for (int i = 0; i < n; i++) {        long long income;        int k;        scanf("%lld %d", &income, &k);        long long base = income - 1500000LL * k;        if (base < 0) base = 0;         long long total = 0; /* 세율을 곱한 값을 쌓는다(최대 약 4.5조라 int로는 넘친다) */        int rate = 0;        for (int b = 0; b < 8; b++) {            if (base <= LOW[b]) break;            long long top = base;            if (b + 1 < 8 && LOW[b + 1] < top) top = LOW[b + 1];            total += (top - LOW[b]) * RATE[b];            rate = RATE[b];        }        long long tax = total / 100;         long long credit;        if (tax <= 1300000) {            credit = tax * 55 / 100;        } else {            credit = 715000 + (tax - 1300000) * 30 / 100;            if (credit > 740000) credit = 740000;        }        printf("%lld %lld %d\n", tax, tax - credit, rate);    }    return 0;}
Craykonmain.cray · 41 줄
// 구간 아래 끝과 세율 % — 아래 끝 초과 다음 아래 끝 이하인 부분에 그 세율아래끝 = [0, 14000000, 50000000, 88000000, 150000000, 300000000, 500000000, 1000000000];세율 = [6, 15, 24, 35, 38, 40, 42, 45]; n = 콘솔.줄읽기().수로변환();반복 (i = 0; i < n; i++){    p = 콘솔.수들읽기();    소득 = p[0];    k = p[1];    과세표준 = 수학.큰수(소득 - 1500000 * k, 0);     합 = 0; // 세율을 곱한 값을 쌓는다(최대 약 4.5조라 2^53 안에서 정확)    한계세율 = 0;    반복 (b = 0; b < 8; b++)    {        만약 (과세표준 <= 아래끝[b])        {            그만;        }        위끝 = 과세표준;        만약 (b + 1 < 8)        {            위끝 = 수학.작은수(과세표준, 아래끝[b + 1]);        }        합 += (위끝 - 아래끝[b]) * 세율[b];        한계세율 = 세율[b];    }    세액 = 수학.몫(합, 100);     공제 = 0;    만약 (세액 <= 1300000)    {        공제 = 수학.몫(세액 * 55, 100);    }    아니면    {        공제 = 수학.작은수(715000 + 수학.몫((세액 - 1300000) * 30, 100), 740000);    }    콘솔.쓰기(세액 + " " + (세액 - 공제) + " " + 한계세율);}