{ }codelper
for 循环嵌套循环64 位整数P0270

数瓷砖墙上贴广告牌的位置

一面楼墙铺满了正方形瓷砖,横向 C 块,纵向 R 排。
广告牌是覆盖 1 块以上整瓷砖的长方形,高 h 排、宽 w 块,都是 1 以上的整数。
广告牌要严格对齐瓷砖的排和列来贴,不能超出墙外,也不旋转。
广告主只买面积 h × w 在 A 以上 B 以下的广告牌。
尺寸 (h, w) 或贴的位置只要有一点不同,就算作不同的情况。
一行给出用空格分开的 R、C、A、B。
按 h 从 1 到 R 的顺序,如果贴高为 h 的广告牌的情况数大于 0,就在一行输出 h 和这个情况数,用一个空格分开。
情况数为 0 的高度不输出。
最后一行输出 "total" 和所有高度的情况数之和,用一个空格分开。
数字只写数字,不加逗号。

输入
1 ≤ R ≤ 500,1 ≤ C ≤ 500,1 ≤ A ≤ B ≤ 250,000(都是整数)
输出
每个有情况的高度一行 "h 情况数",最后一行 "total 总和"
样例 1 · stdin
2 3 2 3
stdout
1 6
2 3
total 9
样例 2 · stdin
3 3 10 20
stdout
total 0
main.py
输入(stdin)

运行时这些行会依次作为 input()/标准输入传入(运行中不会等待输入)。

$ 就绪

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

其他语言怎么写?查看各语言题解 · 8 种语言题解

高度 h 从 1 到 R、宽度 w 从 1 到 C 两层循环,面积符合时加上贴的位置 (R - h + 1) × (C - w + 1) 种。
在 R 排的墙上贴高 h 的广告牌,最上面一排可以在第 1 排到第 R - h + 1 排,所以不是 R - h。
第一个陷阱是循环的终点。
Python 的 range(1, R + 1) 不包含终点值,写成 range(1, R) 就漏掉了 h = R。
JS、TS、Java、C#、C、C++ 写 for (int h = 1; h <= R; h++),Craykon 写 循环 (h = 1; h <= R; h++),用 <= 把终点包含进去。
C# 的 Enumerable.Range(1, R) 第二个参数不是终点而是个数。
第二,内层循环是宽度,要到 C 为止。
在长宽不同的墙(500 × 1)上把 R 和 C 弄反就会出错。
第三,“A 以上 B 以下”两端都包含,所以是 A <= area && area <= B(Python 可以连写成 A <= area <= B,其他语言会报错(Craykon、Java、C#)或意思不同(JS、TS、C、C++ 会拿前一个比较的结果去和 B 比))。
第四个陷阱是大小。
一个高度的情况数在 int 范围内,但 500 × 500 的墙上总和约为 1.6×10^10,所以要加到 C/C++ 的 long long 或 Java/C# 的 long 里。
JS、TS、Craykon 的数在 2^53 以内是精确的,Python 的 int 不会溢出。

Pythonmain.py · 11 行
R, C, A, B = map(int, input().split())total = 0for h in range(1, R + 1):          # range의 끝은 들어가지 않는다: R까지 돌려면 R + 1    count = 0    for w in range(1, C + 1):        if A <= h * w <= B:            count += (R - h + 1) * (C - w + 1)   # 위쪽 줄 R-h+1가지 × 왼쪽 칸 C-w+1가지    if count > 0:        print(h, count)    total += countprint("total", total)
JavaScriptmain.js · 14 行
const [R, C, A, B] = require("fs").readFileSync(0, "utf8").trim().split(/\s+/).map(Number);const out = [];let total = 0; // 최대 약 1.6×10^10: 2^53 안이라 Number로 정확하다for (let h = 1; h <= R; h++) {  let count = 0;  for (let w = 1; w <= C; w++) {    const area = h * w;    if (A <= area && area <= B) count += (R - h + 1) * (C - w + 1);  }  if (count > 0) out.push(`${h} ${count}`);  total += count;}out.push(`total ${total}`);console.log(out.join("\n"));
TypeScriptmain.ts · 15 行
import { readFileSync } from "node:fs";const [R, C, A, B]: number[] = readFileSync(0, "utf8").trim().split(/\s+/).map(Number);const out: string[] = [];let total = 0; // 최대 약 1.6×10^10: 2^53 안이라 number로 정확하다for (let h = 1; h <= R; h++) {  let count = 0;  for (let w = 1; w <= C; w++) {    const area: number = h * w;    if (A <= area && area <= B) count += (R - h + 1) * (C - w + 1);  }  if (count > 0) out.push(`${h} ${count}`);  total += count;}out.push(`total ${total}`);console.log(out.join("\n"));
JavaMain.java · 21 行
import java.util.Scanner; public class Main {    public static void main(String[] args) {        Scanner sc = new Scanner(System.in);        int R = sc.nextInt(), C = sc.nextInt(), A = sc.nextInt(), B = sc.nextInt();        StringBuilder out = new StringBuilder();        long total = 0; // 최대 약 1.6×10^10: int로는 넘친다        for (int h = 1; h <= R; h++) {            long count = 0;            for (int w = 1; w <= C; w++) {                int area = h * w;                if (A <= area && area <= B) count += (long) (R - h + 1) * (C - w + 1);            }            if (count > 0) out.append(h).append(' ').append(count).append('\n');            total += count;        }        out.append("total ").append(total).append('\n');        System.out.print(out);    }}
C#Main.cs · 27 行
using System;using System.Linq;using System.Text; class Program{    static void Main()    {        int[] v = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToArray();        int R = v[0], C = v[1], A = v[2], B = v[3];        var out_ = new StringBuilder();        long total = 0; // 최대 약 1.6×10^10: int로는 넘친다        for (int h = 1; h <= R; h++)        {            long count = 0;            for (int w = 1; w <= C; w++)            {                int area = h * w;                if (A <= area && area <= B) count += (long)(R - h + 1) * (C - w + 1);            }            if (count > 0) out_.Append(h).Append(' ').Append(count).Append('\n');            total += count;        }        out_.Append("total ").Append(total).Append('\n');        Console.Write(out_);    }}
C++main.cpp · 17 行
#include <iostream> int main() {    int R, C, A, B;    std::cin >> R >> C >> A >> B;    long long total = 0; // 최대 약 1.6×10^10: int로는 넘친다    for (int h = 1; h <= R; h++) {        long long count = 0;        for (int w = 1; w <= C; w++) {            int area = h * w;            if (A <= area && area <= B) count += (long long)(R - h + 1) * (C - w + 1);        }        if (count > 0) std::cout << h << ' ' << count << '\n';        total += count;    }    std::cout << "total " << total << '\n';}
Cmain.c · 18 行
#include <stdio.h> int main(void) {    int R, C, A, B;    scanf("%d %d %d %d", &R, &C, &A, &B);    long long total = 0; /* 최대 약 1.6×10^10: int로는 넘친다 */    for (int h = 1; h <= R; h++) {        long long count = 0;        for (int w = 1; w <= C; w++) {            int area = h * w;            if (A <= area && area <= B) count += (long long)(R - h + 1) * (C - w + 1);        }        if (count > 0) printf("%d %lld\n", h, count);        total += count;    }    printf("total %lld\n", total);    return 0;}
Craykonmain.cray · 25 行
v = 控制台.读数字();R = v[0];C = v[1];A = v[2];B = v[3];total = 0; // 최대 약 1.6×10^10: 2^53 안이라 정확하다循环 (h = 1; h <= R; h++){    count = 0;    循环 (w = 1; w <= C; w++)    {        area = h * w;        如果 (A <= area && area <= B)        {            // 위쪽 줄 R-h+1가지 × 왼쪽 칸 C-w+1가지            count += (R - h + 1) * (C - w + 1);        }    }    如果 (count > 0)    {        控制台.输出(h + " " + count);    }    total += count;}控制台.输出("total " + total);