CCCCCHHHHHYFFVB 2025-01-19 14:47 采纳率: 50%
浏览 11

DEV-C++#流星の陨落

#流星の陨落

题目描述

流星雨来了!

当然,这场流星雨确确实实是 Fwb 设计的。Fwb 在天空中放置了许多的流星,同时也在地面上放置了许多的烟花。当流星和烟花发生碰撞时,就会出现美丽而独特的风景。

由于方便控制流星雨的发射,流星的发射是有规律的,这个发射的规律叫做流星间隔。我们把地面上烟花的摆放看作一个数轴,若流星间隔是 $k$,那么在 $i$ 位置发射一颗流星后,下一个发射流星的位置必须是 $i+k$。特殊的,第一个发射流星的位置必须是 $1$。

为了使流星雨好看,保证每一个烟花都会和流星碰撞,即每一个烟花的位置都会有流星发射。但不保证每一个流星都有可碰撞的烟花。为了尽可能减少资源消耗,发射的流星应在满足条件的前提下最少,现在想请你算出,发射的流星雨中最少有多少颗流星以及此时的流星间隔是多少。

输入格式

输入的第一行包含一个正整数 $n$,代表地上共放置了 $n$ 个烟花。

第二行共 $n$ 个正整数,代表烟花在数轴上的位置 $a_i$(保证 $a_i$ 递增)。默认最后一个烟花的位置为数轴的尽头,即保证在位置 $i$($i>a_n$)不会再有流星发射。

输出格式

输出共一行,包含两个正整数,分别表示流星雨中最少的流星数量以及此时的流星间隔。

样例 #1

样例输入 #1

5
1 3 5 7 9

样例输出 #1

5 2

样例 #2

样例输入 #2

7
10 13 19 301 304 307 3004

样例输出 #2

1002 3

样例 #3

样例输入 #3

3
2 1000000 1234567

样例输出 #3

1234567 1

提示

【样例 1 解释】

当流星间隔为 $2$ 时,流星会发射在 $[1,3,5,7,9]$ 的位置,恰好覆盖所有的烟花。此时发射的流星数量最少为 $5$。

【数据范围】

对于所有的测试数据,保证:

  • $1\le n\le 10^5$。
  • 对于任意的 $i$($1\le i\le n$),都有 $1\le a_i\le 10^9$。
测试点$n=$$a_i\le$特殊性质
$1$$1$$10$
$2$$10^5$$10^9$A
$3,4$$10^5$$10^9$B
$5,6,7$$10$$10^9$C
$8,9,10$$10^5$$10^9$

特殊性质 A:保证 $a_i=a_{i-1}+1$($1<i\le n$)。

特殊性质 B:保证 $a_i-a_{i-1}=a_{i+1}-a_i$($1<i<n$)。

特殊性质 C:保证至少出现一次 $a_i-a_{i-1} \le 10^4$($2\le i\le n$)。

题目保证不出现 $n=1$ 且 $a_1=1$ 的情况。
注:请不要用AI生成的代码

  • 写回答

3条回答 默认 最新

  • 关注

    以下回复参考:皆我百晓生券券喵儿等免费微信小程序作答:

    为了解决这个问题,我们可以考虑一个简单的方法来找出满足条件的最小的流星数量和流星间隔。我们知道每个烟花位置必须有流星发射,所以我们可以尝试从第一个烟花开始,每隔一定的间隔发射一颗流星,直到最后一个烟花都有流星覆盖。我们可以通过二分搜索来找到最小的流星间隔。下面是一个可能的解决方案:

    首先,我们需要处理输入数据,获取烟花的位置数组 a 和烟花的数量 n。然后我们可以定义两个函数来辅助解决这个问题:check 函数用来检查给定的流星间隔是否满足条件,binary_search 函数则用来通过二分搜索找到最小的流星间隔。

    以下是实现这个解决方案的C++代码:

    #include <iostream>
    #include <vector>
    #include <algorithm> // for std::sort
    using namespace std;
    
    bool check(const vector<int>& a, int k) {
        int lastPos = a[0]; // 记录上一个烟花的位置,初始化为第一个烟花的位置
        for (int i = 1; i < a.size(); ++i) { // 对于每个烟花的位置
            if ((a[i] - lastPos) % k != 0) { // 如果当前的烟花位置和上一个烟花位置的差不是k的倍数
                return false; // 则不满足条件,返回false
            }
            lastPos = a[i]; // 更新上一个烟花的位置为当前烟花的位置
        }
        return true; // 所有烟花位置都能被流星覆盖,返回true
    }
    
    pair<int, int> findMinimumMeteorShowers(const vector<int>& a) {
        int left = 1; // 最小的可能间隔是1
        int right = a.back() - a.front(); // 最大的可能间隔是最后一个烟花和第一个烟花的距离减一(因为要保证最后一个烟花也有流星发射)
        int n = a.size(); // 烟花的数量也是我们需要发射的流星数量的一部分(至少有一个流星覆盖每个烟花的位置)
        int minMeteorCount = n; // 最少需要的流星数量初始化为烟花数量(至少一个流星对应每个烟花)
        int meteorInterval = -1; // 初始化流星间隔为-1表示没有找到合适的间隔(用于返回结果)
        while (left <= right) { // 二分搜索找到最小的流星间隔
            int mid = left + (right - left) / 2; // 计算中间值作为当前考虑的流星间隔
            if (check(a, mid)) { // 检查这个间隔是否能覆盖所有的烟花位置
                meteorInterval = mid; // 更新流星间隔为当前间隔值(这是我们的目标)
                minMeteorCount += n - 1; // 由于发射位置需要从第一个开始有固定的规律,所以总的流星数量至少是烟花数量加上最后一个位置之后的数量(即n-1)个额外的流星来保证规律性的发射覆盖所有烟花位置。我们需要在每一次找到一个有效的间隔时更新这个数量。这里加上了额外的计算来确定最少的流星数量。            
                right = mid - 1; // 继续搜索更小的间隔值(因为我们要找最小的满足条件的间隔)            
            } else {            
                left = mid + 1; // 继续搜索更大的间隔值(当前的间隔值无法满足覆盖所有烟花位置的条件)            
            }            
        }            
        return make_pair(minMeteorCount, meteorInterval); // 返回最少的流星数量和此时的流星间隔            
    }            
                
    int main() {            
        int n;            
        cin >> n;            
        vector<int> a(n);            
        for (int i = 0; i < n; ++i) {            
            cin >> a[i]; // 输入烟花的位置数组            
        }            
                sort(a.begin(), a.end()); // 保证数组是递增的(如果有必要的话)                  // 根据题目要求可能不需要排序,但确保处理正确需要保证顺序,以便进行二分搜索等计算                   // 如果数组已经有序,则可以省略排序步骤                  // 注意:题目保证a递增,所以排序这一步可以省略。                  // 这里添加代码主要是说明如果在数组顺序无法保证时应该进行的处理                         此处也根据实际的测试用例不需要对输入数据进行排序。        vector<pair<int, int>> specials = {{0}}; // 用于存储特殊性质的标记(如果需要用到的话)        // 根据题目要求填入相关的判断条件              这里不涉及特殊情况处理因此只需要返回一个基本的二元组对结果。        pair<int, int> result = findMinimumMeteorShowers(a);        cout << result.first << " " << result.second << endl;        return 0; }```在这个代码中,我们首先读取输入数据并处理它们。然后调用 `findMinimumMeteorShowers` 函数来找到最小的流星数量和此时的流星间隔。函数通过二分搜索来确定最小的流星间隔,并利用 `check`
    
    评论

报告相同问题?

问题事件

  • 创建了问题 1月19日