基础篇(3)

30 阅读2分钟

一、车厢重组

题目描述

在一个旧式的火车站旁边有一座桥,其桥面可以绕河中心的桥墩水平旋转。一个车站的职工发现桥的长度最多能容纳两节车厢,如果将桥旋转 180 度,则可以把相邻两节车厢的位置交换,用这种方法可以重新排列车厢的顺序。于是他就负责用这座桥将进站的车厢按车厢号从小到大排列。他退休后,火车站决定将这一工作自动化,其中一项重要的工作是编一个程序,输入初始的车厢顺序,计算最少用多少步就能将车厢排序。

输入格式

共两行。

第一行是车厢总数 N(10000)N( \le 10000)

第二行是 N 个不同的数表示初始的车厢顺序。

输出格式

一个整数,最少的旋转次数。

样例 #1

样例输入 #1

4
4 3 2 1

样例输出 #1

6

我的答案

#include <iostream>
#include <utility>
#include <vector>
using namespace std;

int main()
{
    int N;
    cin >> N;
    vector<int> arr(N); // 定义一个可变长度的数组,因为N是变量
    for (int i = 0; i < N; i++)
    {
        cin >> arr[i];
    }
    int times = 0;                  // 记录旋转桥的次数
    for (int i = 0; i < N - 1; i++) // 结合冒泡排序
    {
        for (int j = 0; j < N - i - 1; j++)
        {
            if (arr[j] > arr[j + 1])
            {
                swap(arr[j], arr[j + 1]);
                times++;
            }
        }
    }
    cout << times;
    return 0;
}

值得注意的是,数组的长度一开始并不知道,所以需要写为vector<int>arr(N);vector是动态数组,长度可以在运行时根据需要进行调整。int arr[N];这种写法并不合法,尽管某些编译器可以通过,但不符合C++标准,因为数组长度必须在编译时确定。

二、Peter 的烟

题目描述

Peter 有 n 根烟,他每吸完一根烟就把烟蒂保存起来,k(k>1)个烟蒂可以换一个新的烟,那么 Peter 最终能吸到多少根烟呢?

吸烟有害健康。

输入格式

每组测试数据一行包括两个整数 n,k1<n,k108n, k(1 < n, k \le 10^8)

输出格式

对于每组测试数据,输出一行包括一个整数表示最终烟的根数。

样例 #1

样例输入 #1

4 3

样例输出 #1

5

样例 #2

样例输入 #2

10 3

样例输出 #2

14

提示

对于 100% 的数据,1<n

我的答案

#include <iostream>
using namespace std;

int main()
{
    int n, k;
    cin >> n >> k;
    int num = n;
    while (n >= k)
    {
        num += n / k;
        n = n / k + n % k;
    }
    cout << num;
    return 0;
}

错解

#include <iostream>
using namespace std;

int main()
{
    int n, k;
    cin >> n >> k;
    int num = n;
    while (n / k != 0)
    {
        num += n / k;
        n -= n / k * k;
    }
    cout << num;
    return 0;
}

错误原因:n-=n/k*k有误,n/k的数目其实有可能再去换烟(如样例2)。n-=n/k*k其实表示的是第一轮未参与换烟的数目,而不是参与第二轮换烟的数目。

其他方法(数学解法)

通过解方程可以得到的总数为x=n+n1k1x=n+\frac{n-1}{k-1}​,这样的时间复杂度更低,答案略。

三、子数整数

题目描述

对于一个五位数a1a2a3a4a5a_1a_2a_3a_4a_5,可将其拆分为三个子数:

sub1=a1a2a3sub_1=a_1a_2a_3

sub2=a2a3a4sub_2=a_2a_3a_4

sub3=a3a4a5sub_3=a_3a_4a_5

例如,五位数20207可以拆分成

sub1=202sub_1=202

sub2=020(=20)sub_2=020(=20)

sub3=207sub_3=207

现在给定一个正整数K,要求你编程求出10000到30000之间所有满足下述条件的五位数,条件是这些五位数的三个子数sub1,sub2,sub3sub_1,sub_2,sub_3都可被K整除。

输入格式

一个正整数K

输出格式

每一行为一个满足条件的五位数,要求从小到大输出。不得重复输出或遗漏。如果无解,则输出“No”。

样例 #1

样例输入 #1

15

样例输出 #1

22555
25555
28555
30000

提示

0

我的答案

#include <iostream>
using namespace std;
bool is(int num, int k)
{
    int sub1 = num / 100;
    int sub2 = num / 10 % 1000;
    int sub3 = num % 1000;
    return sub1 % k == 0 && sub2 % k == 0 && sub3 % k == 0;
}
int main()
{
    int K;
    cin >> K;
    int flag = 0;
    for (int i = 10000; i <= 30000; i++)
    {
        if (is(i, K))
        {
            cout << i << endl;
            flag = 1;
        }
    }
    if (flag == 0)
        cout << "No";
    return 0;
}