第五届传智杯【初赛】- C-莲子的排版设计学

C-莲子的排版设计学

题目预览

在这里插入图片描述

image-20221127113716182

image-20221127113725788

题目背景(推荐阅读 题目预览)

如果遇到提交失败,请多次刷新,多次提交,会有成功几率

你现在不能休息,周围有 deadline 在游荡。

莲子正在赶自己的程序设计作业。除了完成程序代码的编写,对提交上去的作业进行排版以对助教留下良好印象同样重要。

而众所周知,文章里面的代码和一些特殊性质的文本是要附上行号的,然而它们的篇幅往往都很长,手动去加容易出现失误。因此,莲子决定自力更生造轮子,写一个行号生成器。

题目描述

莲子希望实现这样一个功能:输入一份文本文件,并给该文件加上行号。

以下是本题中三个基本概念的定义:

  • 文本字符 ASCII \textsf{ASCII} ASCII 中所有的可视字符,以及空格( ASCII = 32 \textsf{ASCII}=32 ASCII=32)组成。
  • 一行字符由若干个(可以为 0 0 0 个)文本字符,以及在末尾恰好一个换行符( ASCII = 10 \textsf{ASCII}=10 ASCII=10)组成。
  • 文本文件由若干个(至少为 1 1 1 个)一行字符组成。文本文件的行数就是组成它的行的数量。

以下是本题中添加行号的方法:

  • 设该文本文件一共有 m m m 行。设正整数 m m m 的字宽为 s s s。那么,在每一行的开头会有 s + 1 s+1 s+1 的长度用来显示行号。
  • 对于第 i i i 行,假设 i i i 的字宽为 t t t,那么这一行行号将会显示为 ␣␣...␣ ⏟ s − t  个   i   ␣ \underbrace{\texttt{␣␣...␣}}_{s-t\text{ 个}}\ i\ \texttt{␣} st  ␣␣...␣ i ,其中 ␣ \texttt{␣} 表示空格。

以下是一个例子:

#include<iostream> using namespace std; int main(){     int a, b;     cin >> a >> b;     cout << a + b << endl;     cout << a - b << endl;     cout << a * b << endl;     cout << a / b << endl;     return 0; } ⇒  1 #include<iostream>  2 using namespace std;  3 int main(){  4     int a, b;  5     cin >> a >> b;  6     cout << a + b << endl;  7     cout << a - b << endl;  8     cout << a * b << endl;  9     cout << a / b << endl; 10     return 0; 11 } \boxed{\begin{aligned} &\verb!#include<iostream>!\\ &\verb!using namespace std;!\\ &\verb!int main(){!\\ &\verb! int a, b;!\\ &\verb! cin >> a >> b;!\\ &\verb! cout << a + b << endl;!\\ &\verb! cout << a - b << endl;!\\ &\verb! cout << a * b << endl;!\\ &\verb! cout << a / b << endl;!\\ &\verb! return 0;!\\ &\verb!}! \end{aligned}} \Rightarrow \boxed{\begin{aligned} &\verb! 1 #include<iostream>!\\ &\verb! 2 using namespace std;!\\ &\verb! 3 int main(){!\\ &\verb! 4 int a, b;!\\ &\verb! 5 cin >> a >> b;!\\ &\verb! 6 cout << a + b << endl;!\\ &\verb! 7 cout << a - b << endl;!\\ &\verb! 8 cout << a * b << endl;!\\ &\verb! 9 cout << a / b << endl;!\\ &\verb!10 return 0;!\\ &\verb!11 }! \end{aligned}} #include<iostream>using namespace std;int main(){    int a, b;    cin >> a >> b;    cout << a + b << endl;    cout << a - b << endl;    cout << a * b << endl;    cout << a / b << endl;    return 0;} 1 #include<iostream> 2 using namespace std; 3 int main(){ 4     int a, b; 5     cin >> a >> b; 6     cout << a + b << endl; 7     cout << a - b << endl; 8     cout << a * b << endl; 9     cout << a / b << endl;10     return 0;11 }
为了便于读者观察,这里将所有的空格换成用来表示空格的 ␣ \verb!␣! 字符。

#include<iostream> using␣namespace␣std; int␣main(){ ␣␣␣␣int␣a,␣b; ␣␣␣␣cin␣>>␣a␣>>␣b; ␣␣␣␣cout␣<<␣a␣+␣b␣<<␣endl; ␣␣␣␣cout␣<<␣a␣-␣b␣<<␣endl; ␣␣␣␣cout␣<<␣a␣*␣b␣<<␣endl; ␣␣␣␣cout␣<<␣a␣/␣b␣<<␣endl; ␣␣␣␣return␣0; } ⇒ ␣1␣#include<iostream> ␣2␣using␣namespace␣std; ␣3␣int␣main(){ ␣4␣␣␣␣␣int␣a,␣b; ␣5␣␣␣␣␣cin␣>>␣a␣>>␣b; ␣6␣␣␣␣␣cout␣<<␣a␣+␣b␣<<␣endl; ␣7␣␣␣␣␣cout␣<<␣a␣-␣b␣<<␣endl; ␣8␣␣␣␣␣cout␣<<␣a␣*␣b␣<<␣endl; ␣9␣␣␣␣␣cout␣<<␣a␣/␣b␣<<␣endl; 10␣␣␣␣␣return␣0; 11␣} \boxed{\begin{aligned} &\verb!#include<iostream>!\\ &\verb!using␣namespace␣std;!\\ &\verb!int␣main(){!\\ &\verb!␣␣␣␣int␣a,␣b;!\\ &\verb!␣␣␣␣cin␣>>␣a␣>>␣b;!\\ &\verb!␣␣␣␣cout␣<<␣a␣+␣b␣<<␣endl;!\\ &\verb!␣␣␣␣cout␣<<␣a␣-␣b␣<<␣endl;!\\ &\verb!␣␣␣␣cout␣<<␣a␣*␣b␣<<␣endl;!\\ &\verb!␣␣␣␣cout␣<<␣a␣/␣b␣<<␣endl;!\\ &\verb!␣␣␣␣return␣0;!\\ &\verb!}! \end{aligned}} \Rightarrow \boxed{\begin{aligned} &\verb!␣1␣#include<iostream>!\\ &\verb!␣2␣using␣namespace␣std;!\\ &\verb!␣3␣int␣main(){!\\ &\verb!␣4␣␣␣␣␣int␣a,␣b;!\\ &\verb!␣5␣␣␣␣␣cin␣>>␣a␣>>␣b;!\\ &\verb!␣6␣␣␣␣␣cout␣<<␣a␣+␣b␣<<␣endl;!\\ &\verb!␣7␣␣␣␣␣cout␣<<␣a␣-␣b␣<<␣endl;!\\ &\verb!␣8␣␣␣␣␣cout␣<<␣a␣*␣b␣<<␣endl;!\\ &\verb!␣9␣␣␣␣␣cout␣<<␣a␣/␣b␣<<␣endl;!\\ &\verb!10␣␣␣␣␣return␣0;!\\ &\verb!11␣}! \end{aligned}} #include<iostream>using␣namespace␣std;int␣main(){␣␣␣␣int␣a,␣b;␣␣␣␣cin␣>>␣a␣>>␣b;␣␣␣␣cout␣<<␣a␣+␣b␣<<␣endl;␣␣␣␣cout␣<<␣a␣-␣b␣<<␣endl;␣␣␣␣cout␣<<␣a␣*␣b␣<<␣endl;␣␣␣␣cout␣<<␣a␣/␣b␣<<␣endl;␣␣␣␣return␣0;}␣1␣#include<iostream>␣2␣using␣namespace␣std;␣3␣int␣main(){␣4␣␣␣␣␣int␣a,␣b;␣5␣␣␣␣␣cin␣>>␣a␣>>␣b;␣6␣␣␣␣␣cout␣<<␣a␣+␣b␣<<␣endl;␣7␣␣␣␣␣cout␣<<␣a␣-␣b␣<<␣endl;␣8␣␣␣␣␣cout␣<<␣a␣*␣b␣<<␣endl;␣9␣␣␣␣␣cout␣<<␣a␣/␣b␣<<␣endl;10␣␣␣␣␣return␣0;11␣}

输入格式

输入包含若干行,为原始的文本文件。

输出格式

输出包含若干行,为加上行号后的文本文件。

样例 #1

样例输入 #1

#include<iostream>
using namespace std;
int main(){
    int a, b;
    cin >> a >> b;
    cout << a + b << endl;
    cout << a - b << endl;
    cout << a * b << endl;
    cout << a / b << endl;
    return 0;
}

样例输出 #1

1 #include<iostream>
 2 using namespace std;
 3 int main(){
 4     int a, b;
 5     cin >> a >> b;
 6     cout << a + b << endl;
 7     cout << a - b << endl;
 8     cout << a * b << endl;
 9     cout << a / b << endl;
10     return 0;
11 }

样例 #2

样例输入 #2

public class Main {
    public static void main(String[] args) throws Exception {
        int b = 0, c = 0;
        for (int a = 123; a < 333; a++) {
            int[] array = new int[10];
            Boolean flag = true;
            b = a * 2;
            c = a * 3;
            array[a / 100] = 1;
            array[a / 10 % 10] = 1;
            array[a % 10] = 1;

            array[b / 100] = 1;
            array[b / 10 % 10] = 1;
            array[b % 10] = 1;

            array[c / 100] = 1;
            array[c / 10 % 10] = 1;
            array[c % 10] = 1;
            for (int i = 1; i < array.length; i++) {
                if (array[i] != 1) {
                    flag = false;
                    break;
                }
            }
            if (flag)
                System.out.println(a + " " + b + " " + c);
        }
    }
}

样例输出 #2

1 public class Main {
 2     public static void main(String[] args) throws Exception {
 3         int b = 0, c = 0;
 4         for (int a = 123; a < 333; a++) {
 5             int[] array = new int[10];
 6             Boolean flag = true;
 7             b = a * 2;
 8             c = a * 3;
 9             array[a / 100] = 1;
10             array[a / 10 % 10] = 1;
11             array[a % 10] = 1;
12 
13             array[b / 100] = 1;
14             array[b / 10 % 10] = 1;
15             array[b % 10] = 1;
16 
17             array[c / 100] = 1;
18             array[c / 10 % 10] = 1;
19             array[c % 10] = 1;
20             for (int i = 1; i < array.length; i++) {
21                 if (array[i] != 1) {
22                     flag = false;
23                     break;
24                 }
25             }
26             if (flag)
27                 System.out.println(a + " " + b + " " + c);
28         }
29     }
30 }

样例 #3

样例输入 #3

Tao hua kai yo li hua kai, jie jie mei mei dong qi lai;
Tao hua kai yo li hua kai, jie jie mei mei tiao qi lai.
    Gei ni zi ji, chun yi mai huai (yi ya yo);
    Gei xin shang ren, chun se man kai.
Tao hua kai yo li hua kai, jie jie mei mei dong qi lai; 
Tao hua kai yo li hua kai, jie jie mei mei tiao qi lai.
    Gei tong bao men, chun yi man huai, hai hai yo;
    Gei zhe da di, chun se quan kai!!!
Cong na nu jiang nan, dao mo he bei,
    Dao chu dou you hua rong ming mei.
Lai hui hui shou, zai diao ge tou,
    Wu xian chun guang zai wo xiong.
Cong jing cheng, dao yuan ye,
    Dao chu dou you sheng de xi yue.
Lai hui hui shou, zai yan ran huang ge tou,
    Wu xian CHUN GUANG XIAN ZU GUO!!!
Tao hua kai yo li hua kai, Jiong xian mei mei dong qi lai;
Tao hua kai yo li hua kai, Jie jie mei mei tiao qi lai.
    Gei ni zi ji, chun yi mai huai chun yi man huai yi ya yo;
    Gei xin shang ren, chun se man kai chun se man kai.
Tao hua kai yo li hua kai, Jie jie mei mei dong qi lai;
Tao hua kai yo li hua kai, Jie jie mei mei tiao qi lai.
    Gei tong bao men, chun yi man huai, hai hai yo;
    Gei zhe da di, chun se quan kai!!!
Cong na nu jiang nan, dao mo he bei,
    Dao chu dou you hua rong ming mei.
Lai hui hui shou, zai diao ge tou,
    Wu xian chun guang zai wo xiong.
Cong jing cheng, dao yuan ye,
    Dao chu dou you sheng de xi yue.
Lai hui hui shou, zai yan ran huang ge tou,
    Wu xian CHUN GUANG XIAN ZU GUO!!!
Lai hui hui shou, zai yan ran huang ge tou,
    Wu xian CHUN GUANG XIAN ZU GUO!!!

样例输出 #3

1 Tao hua kai yo li hua kai, jie jie mei mei dong qi lai;
 2 Tao hua kai yo li hua kai, jie jie mei mei tiao qi lai.
 3     Gei ni zi ji, chun yi mai huai (yi ya yo);
 4     Gei xin shang ren, chun se man kai.
 5 Tao hua kai yo li hua kai, jie jie mei mei dong qi lai; 
 6 Tao hua kai yo li hua kai, jie jie mei mei tiao qi lai.
 7     Gei tong bao men, chun yi man huai, hai hai yo;
 8     Gei zhe da di, chun se quan kai!!!
 9 Cong na nu jiang nan, dao mo he bei,
10     Dao chu dou you hua rong ming mei.
11 Lai hui hui shou, zai diao ge tou,
12     Wu xian chun guang zai wo xiong.
13 Cong jing cheng, dao yuan ye,
14     Dao chu dou you sheng de xi yue.
15 Lai hui hui shou, zai yan ran huang ge tou,
16     Wu xian CHUN GUANG XIAN ZU GUO!!!
17 Tao hua kai yo li hua kai, Jiong xian mei mei dong qi lai;
18 Tao hua kai yo li hua kai, Jie jie mei mei tiao qi lai.
19     Gei ni zi ji, chun yi mai huai chun yi man huai yi ya yo;
20     Gei xin shang ren, chun se man kai chun se man kai.
21 Tao hua kai yo li hua kai, Jie jie mei mei dong qi lai;
22 Tao hua kai yo li hua kai, Jie jie mei mei tiao qi lai.
23     Gei tong bao men, chun yi man huai, hai hai yo;
24     Gei zhe da di, chun se quan kai!!!
25 Cong na nu jiang nan, dao mo he bei,
26     Dao chu dou you hua rong ming mei.
27 Lai hui hui shou, zai diao ge tou,
28     Wu xian chun guang zai wo xiong.
29 Cong jing cheng, dao yuan ye,
30     Dao chu dou you sheng de xi yue.
31 Lai hui hui shou, zai yan ran huang ge tou,
32     Wu xian CHUN GUANG XIAN ZU GUO!!!
33 Lai hui hui shou, zai yan ran huang ge tou,
34     Wu xian CHUN GUANG XIAN ZU GUO!!!

提示

数据范围及约定

对于全部数据,保证输入的文本文件的字符总数(包括换行符在内),不超过 2 × 1 0 4 2\times 10^4 2×104。同时,保证输入数据合法。

评测时,会忽略选手输出文件的行末空格与文末换行。因此选手可以自行决定行尾是否要输出多余空格。请使用 Java 或 Python 语言作答的选手注意输入输出时的效率。

题解

  • 题解全览

image-20221127113912446

读入题。暴风吸入输入数据里给定的所有字符,存到数组里,统计有多少个换行符,确定输入文件的总行数 m。由此计算出最后一个行号的长度 s=⌊lgm+1⌋(数学库里可以直接调用 lg,当然你也可以随便用什么途径算出每个数的长度)。

然后就是模拟了。对于第 i*i 行,

  • 计算出 i 的长度 t=⌊lgi+1⌋。
  • 输出 st 个空格,再输出 i,然后输出 1 个空格。
  • 从第 i−1 个换行的位置开始,一直到第 i 个换行,把中间的字符全部输出。这样第 i 行就做完了。

时间复杂度为O(∣S∣),其中∣S∣ 是输入的所有字符的个数。

参考代码

  • 版本1:
    #include<bits/stdc++.h>
    #define up(l, r, i) for(int i = l, END##i = r;i <= END##i;++ i)
    #define dn(r, l, i) for(int i = r, END##i = l;i >= END##i;-- i)
    using namespace std;
    typedef long long i64;
    const int INF = 2147483647;
    const int MAXN= 2e4 + 3;
    char S[MAXN], c; int l, m;
    int main(){
        m = count(S + 1 , S + 1 + fread(S + 1, 1, MAXN, stdin), '\n');
        int s = log10(m) + 1 + 1e-9, p = 0;
        up(1, m, i){
            int t = log10(i) + 1 + 1e-9;
            for(int j = 1;j <= s - t;++ j) putchar( ' '); printf("%d ", i);
            for(p = p + 1;S[p] != 10;++ p) putchar(S[p]); putchar('\n');
        }
        return 0;
    }
    
  • 版本2:
    #include <iostream>
    #include <cstdio>
    #include <vector>
    using namespace std;
    char buf[200050];
    vector <char> s[200050];
    int cnt;
    int get_digit(int x)
    {
        int digit=1,ret=1;
        while (ret<=x)
        {
            digit++;
            ret*=10;
        }
        return digit;
    }
    int main()
    {
        while(fgets(buf,200000,stdin)!=NULL)
        {
            cnt++;
            for (int i=0;buf[i]!='\n';i++)
                s[cnt].push_back(buf[i]);
        }
        int cnt_digit=get_digit(cnt);
        for (int i=1;i<=cnt;i++)
        {
            for (int j=1;j<=cnt_digit-get_digit(i);j++)
                putchar(' ');
            cout << i << ' ';
            for (int j=0;j<s[i].size();j++)
                putchar(s[i][j]);
            putchar('\n');
        }
        return 0;
    }
    
  • 版本3:
    import java.util.Scanner;
    import java.util.List;
    import java.util.ArrayList;
    
    public class Main {
    
        public static List<String> list = new ArrayList<>();
    
        public static int getBit(int x) {
            int cnt = 0;
            while (x > 0) {
                x /= 10;
                ++cnt;
            }
            return cnt;
        }
    
        public static void main(String[] args) {
            Scanner scanner = new Scanner(System.in);
            while (scanner.hasNextLine()) {
                list.add(scanner.nextLine());
            }
            int size = list.size();
            int len = getBit(size);
            for (int i = 0; i < size; ++i) {
                System.out.printf("%" + len + "d %s\n", i + 1, list.get(i));
            }
        }
    }
    
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值