{ }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()/标准输入传入(运行中不会等待输入)。

$ 就绪

请在电脑上打开以编写和运行代码。在手机上可以查看题目和题解。

其他语言怎么写?查看各语言题解 · 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、Craykon 只有一种数(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),Craykon 数学.商(a, 100)。
抵免是两路 if-else:Python if … else:,Craykon 如果 … 否则。
上限 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);    }    控制台.输出(세액 + " " + (세액 - 공제) + " " + 한계세율);}