Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.50/8: Рейтинг темы: голосов - 8, средняя оценка - 4.50
0 / 0 / 0
Регистрация: 25.11.2022
Сообщений: 19

Найти размер наибольшего братства в массиве (оптимизация кода)

09.05.2024, 17:19. Показов 1740. Ответов 13
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Задан массив a
состоящий из различных целых положительных чисел.

Назовём подмассив ai,ai+1,…,aj братством только в том случае, если существует целое число m≥2 такое, что aimodm=ai+1modm=…=ajmodm, где xmody это математический остаток от целочисленного деления x на y.

Вам нужно найти размер наибольшего братства в массиве a.

Входные данные
В каждом тесте задано несколько независимых наборов входных данных. В первой строке входных данных указано количество этих наборов t (1≤t≤2⋅104).

В первой строке каждого набора задано целое число n
(1≤n≤2⋅105) – размер массива a.

Во второй строке каждого набора содержится n целых положительных чисел a1,a2,…,an (1≤ai≤1018) – составляющих массив a. Гарантируется, что все числа в a различны.

Гарантируется, что сумма n по всем наборам входных данных меньше 2⋅105.

Выходные данные
Выведите t
строк. В каждой строке должно содержаться единственное целое число — размер наибольшего братства в a
.
Мое решение не проходит по времени, я думаю что он неэффективно перебирает m, подскажите как можно оптимизировать код. Братство это рядом стоящие элементы если что.
Вот мой код
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <bits/stdc++.h>  
using namespace std;  
#define int int64_t  
signed main() {  
    ios::sync_with_stdio(0);   
    cin.tie(0);  
    int t;  
    cin >> t;  
    while (t--) {  
        int n;  
        cin >> n;  
        vector<int> vec(n);  
        for (int i = 0; i < n; ++i) cin >> vec[i];  
        int ans = 0;  
        int m = -1;  
        for (int h = 0; h < n; ++h) {  
            if (vec[h] > m) m = vec[h];   
        } 
 
        for (int i = 0; i < n; ++i) {  
            for (int s = 2; s <= m; ++s) {  
                int l = vec[i] % s;  
                int anss = 1;  
                for (int h = i + 1; h < n; ++h) {  
                    if (vec[h] % s == l) anss++;  
                    else break;  
                }   
                if (anss > ans) ans = anss;  
            }  
        }  
        cout << ans << "\n";  
    }  
    return 0;  
}
Пример
Входные данные

4
5
1 5 2 4 6
4
8 2 5 10
2
2000 1000
8
465 55 3 54 234 12 45 78

Выходные данные

3
3
2
6
Примечание

В первом наборе массив это [1,5,2,4,6]. Наибольшее братство это [2,4,6], поскольку все эти числа имеют остаток 0 по модулю 2, следовательно, m=2.

Во втором наборе массив это [8,2,5,10]. Наибольшее братство это [8,2,5], поскольку все эти числа имеют остаток 2 по модулю 3, следовательно, m=3.

В третьем наборе наибольшее братство это [2000,1000]. Можно привести несколько подходящих значений m.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
09.05.2024, 17:19
Ответы с готовыми решениями:

Оптимизация кода поиска наибольшего и наименьшего числа
Ребята, Java изучаю по книжке. Хотелось бы увидеть решение от гуру, чтоб знать к чему стремиться. Например такая задача: Ввести с консоли...

Найти размер наибольшего префикса
У вас есть n вершин и список из m ребер. Назовем префиксом списка его первые k элементов. Найдите наибольший(по длине) префикс списка...

Найти индекс наибольшего числа в массиве
Необходимо решить 3 задачи. Времени разбираться, читать книгу по C# уже нет, да и болезнь не дает нормально мыслить. Поэтому просьба -...

13
 Аватар для lemegeton
4903 / 2696 / 921
Регистрация: 29.11.2010
Сообщений: 5,783
09.05.2024, 19:09
У вас сложность кубическая. Должен быть квадрат.


Есть такое свойство: если два числа имеют одинаковый остаток от деления на m, то их разница делится на m.
Это называется "сравнение по модулю m".

Отсюда вывод, что одинаковый остаток будет у всех делителей модуля разницы. Единичку, естественно, не считаем.
Например, числа 150 и 12. Разница 138. Делители: 2, 3, 6, 23, 46, 69, 138.
Например, числа 12 и 47. Разница 35. Делители: 5, 7, 35
Например, числа 150 и 219. Разница 69. Делители: 3, 23, 69

Если три числа имеют одинаковый остаток от деления на m это означает, что наибольший общий делитель (НОД) их разниц отличается от единицы.
Например, 150, 12, 47. Разницы -- 138, 35. НОД(138, 25) = 1 -- нет такого числа.
Например, 150,219,12. Разницы -- 69,207. НОД(69,207) = 69. Есть такое число. Все числа, дающие в остатке одинаковое число это делители 69 -- 3, 23, 69.

При увеличении количества сравниваемых чисел надо брать НОД от НОД.

Соответственно, алгоритм примерно такой.

Находим разницы всех пар чисел. Получаем массив разностей размером n-1.
Проходимся попарно нодами и записываем НОДы в массив размером n-2. Если все 1, то ответ 2, иначе...
По резульатам проходимся попарно НОДами, записывая в массив размером n-3. Если все 1, то ответ 3, иначе...
и так далее, уменьшая размер нового массива на единицу и увеличивая ответ на единицу. Пока не найдем все 1 или пока не останется 1 элемент. Тогда ответ n.

Добавлено через 43 минуты
Вот как-то так (надо отладить):
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#include <iostream>
#include <vector>
#include <numeric>
 
/*
template<typename T>
std::ostream &operator<<(std::ostream &out, const std::vector<T> &v) {
    for (auto i = v.begin(), end = v.end(); i != end;) {
        out << *i;
        if (++i != end) {
            out << ',';
        }
    }
    return out;
}
*/
 
template<typename T>
std::istream &operator>>(std::istream &in, std::vector<T> &vector) {
    size_t size;
    in >> size;
    T value;
    while (size--) {
        in >> value;
        vector.push_back(value);
    }
    return in;
}
 
template<typename T>
std::vector<T> operator-(const std::vector<T> &vector) {
    std::vector<T> result{};
    result.reserve(vector.size() - 1);
 
    for (size_t i = 1, size = vector.size(); i < size; ++i) {
        result.push_back(std::abs(std::abs(vector[i - 1]) - std::abs(vector[i])));
    }
    return result;
}
 
template<typename T>
std::pair<bool, std::vector<T>> iterate(const std::vector<T> &v) {
    std::vector<T> result{};
    result.reserve(v.size() - 1);
 
    bool contains = false;
    for (size_t i = 1, size = v.size(); i < size; ++i) {
        auto gcd = std::gcd(v[i - 1], v[i]);
        result.push_back(gcd);
        if (gcd != 1) {
            contains = true;
        }
    }
 
    return {contains, result};
}
 
int main() {
 
    std::size_t count;
    std::cin >> count;
 
 
    while (count--) {
 
        std::vector<std::int64_t> array;
        std::cin >> array;
//        std::cout << "DEBUG: " << array << std::endl;
//        std::cout << "DEBUG: " << -array << std::endl;
 
        size_t answer = 2;
        for (auto next = iterate(-array); next.first && next.second.size() > 1; next = iterate(next.second)) {
            ++answer;
//            std::cout << "DEBUG: " << std::boolalpha << next.first << ": " << next.second << std::endl;
        }
        std::cout << answer << std::endl;
    }
    return 0;
}
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12942 / 6809 / 1821
Регистрация: 18.10.2014
Сообщений: 17,234
09.05.2024, 19:20
Цитата Сообщение от Artem Ka Посмотреть сообщение
1≤t≤2⋅104
Что за странная запись? Почему вместо того, чтобы просто написать 208, написали 2⋅104?
0
Эксперт функциональных языков программированияЭксперт С++
 Аватар для Royal_X
6221 / 2919 / 1046
Регистрация: 01.06.2021
Сообщений: 10,810
09.05.2024, 19:27
Цитата Сообщение от Artem Ka Посмотреть сообщение
105
10^5 ?
Цитата Сообщение от Artem Ka Посмотреть сообщение
104
10^4 ?
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12942 / 6809 / 1821
Регистрация: 18.10.2014
Сообщений: 17,234
09.05.2024, 21:10
Цитата Сообщение от Artem Ka Посмотреть сообщение
подскажите как можно оптимизировать код.
Никак, разумеется. Откуда вообще возникла идея делать то, что вы делаете в своем коде?

Цитата Сообщение от lemegeton Посмотреть сообщение
Соответственно, алгоритм примерно такой.
Мне навскидку пришел в голову вариант с факторизацией каждой разницы соседних (степени факторов значения не имеют, имеет значение лишь спектр уникальных факторов) и поиск наибольшего по длине непрерывного повторения одного и того же фактора. Реализуется несложно, но это, наверное, будет существенно менее эффективно, чем ваш вариант, основанный на НОД.

Что-то вроде

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#include <cassert>
#include <utility>
#include <vector>
#include <algorithm>
#include <iostream>
 
std::vector<unsigned> unique_factors(unsigned v)
{
  std::vector<unsigned> r;
 
  for (unsigned d = 2; d * d <= v; ++d)
    if (v % d == 0)
    {
      r.push_back(d);
      for (v /= d; v % d == 0; v /= d);
    }
 
  if (v != 1)
    r.push_back(v);
 
  assert(std::is_sorted(r.begin(), r.end()));
  return r;
}
 
int main() 
{ 
  const unsigned MIN = 1, MAX = 100000;
  std::vector<bool> b(MAX - MIN);
 
  unsigned n = 100;
  std::vector<unsigned> a(n);
  for (unsigned &v : a)
  {
    do v = MIN + std::rand() % (MAX - MIN); while (b[v - MIN]);
    b[v - MIN] = true;
  }
 
  std::vector<std::pair<unsigned, unsigned>> curr_factors;
  unsigned n_max_length = 0, i_max_start, max_factor;
 
  for (unsigned i = 1; i < n; ++i)
  {
    unsigned diff = a[i] > a[i - 1] ? a[i] - a[i - 1] : a[i - 1] - a[i];
    auto factors = unique_factors(diff);
 
    auto it_curr = curr_factors.begin();
    auto it_new = factors.begin();
    while (it_curr != curr_factors.end() && it_new != factors.end())
      if (*it_new < it_curr->first)
      { // New run begins
        it_curr = curr_factors.emplace(it_curr, *it_new, i);
        ++it_new;
        ++it_curr;
      }
      else if (*it_new > it_curr->first)
      { // Existing run ends
        unsigned n_length = i - it_curr->second;
        if (n_length > n_max_length)
        {
          n_max_length = n_length;
          i_max_start = it_curr->second;
          max_factor = it_curr->first;
        }
 
        it_curr = curr_factors.erase(it_curr);
      }
      else
      { // Existing run continues
        ++it_new;
        ++it_curr;
      }
 
    // Process remaining tails, if any
 
    if (it_new != factors.end())
    {
      for (; it_new != factors.end(); ++it_new)
        // New run begins
        curr_factors.emplace_back(*it_new, i);
    }
    else
    {
      for (auto it = it_curr; it != curr_factors.end(); ++it)
      { // Existing run ends
        unsigned n_length = i - it->second;
        if (n_length > n_max_length)
        {
          n_max_length = n_length;
          i_max_start = it_curr->second;
          max_factor = it_curr->first;
        }
      }
 
      curr_factors.erase(it_curr, curr_factors.end());
    }
 
    assert(std::is_sorted(curr_factors.begin(), curr_factors.end()));
  }
 
  std::cout << n_max_length + 1 << std::endl;
  std::cout << std::endl;
 
  std::cout << max_factor << std::endl;
  for (unsigned i = i_max_start - 1; i < i_max_start + n_max_length; ++i)
    std::cout << a[i] << " ";
  std::cout << std::endl;
}
1
0 / 0 / 0
Регистрация: 25.11.2022
Сообщений: 19
10.05.2024, 15:25  [ТС]
Спасибо за идею, а вот эта штука как работает
C++
1
return {contains, result};
0
Эксперт функциональных языков программированияЭксперт С++
 Аватар для Royal_X
6221 / 2919 / 1046
Регистрация: 01.06.2021
Сообщений: 10,810
10.05.2024, 16:47
Цитата Сообщение от Artem Ka Посмотреть сообщение
вот эта штука как работает
работает как std::make_pair
2
0 / 0 / 0
Регистрация: 25.11.2022
Сообщений: 19
11.05.2024, 16:31  [ТС]
Цитата Сообщение от lemegeton Посмотреть сообщение
Находим разницы всех пар чисел. Получаем массив разностей размером n-1.
Проходимся попарно нодами и записываем НОДы в массив размером n-2. Если все 1, то ответ 2, иначе...
По резульатам проходимся попарно НОДами, записывая в массив размером n-3. Если все 1, то ответ 3, иначе...
и так далее, уменьшая размер нового массива на единицу и увеличивая ответ на единицу. Пока не найдем все 1 или пока не останется 1 элемент. Тогда ответ n.
Написал код по вашей идее, та же ошибка на 3 тесте:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <bits/stdc++.h>
using namespace std;
signed main() {
    ios::sync_with_stdio(0);   
    cin.tie(0);  
    long long n;
    cin >> n;
    for (long long i = 0; i < n; ++i) {
        long long x;
        cin >> x;
        vector<long long> g(x);
        for (long long j = 0; j < x; ++j) cin >> g[j];
        vector<long long> vec;
        for (long long j = 0; j < g.size()-1; ++j) {
            vec.push_back(abs(abs(g[j]) - abs(g[j+1])));
        }
        while (vec.size()!=1) {
            vector<long long> a;
            for (long long j = 0; j < vec.size()-1; ++j) {
                a.push_back(gcd(vec[j], vec[j+1]));
            }
            if (count(a.begin(), a.end(), 1) == a.size()){
                cout << x - a.size() << "\n";
                break;
            } else {
                vec.assign(a.begin(),a.end());
                a.clear();
            }
        }
        if (vec.size() == 1) cout << x << "\n";
    }
    return 0;
}
Может можно как то еще ускорить программу

Добавлено через 41 минуту
Цитата Сообщение от lemegeton Посмотреть сообщение
Вот как-то так (надо отладить):
Этот код тоже не проходит
0
458 / 294 / 191
Регистрация: 23.06.2018
Сообщений: 678
11.05.2024, 17:00
Artem Ka, куча перевыделений памяти и лишних копирований.
Во время инициализации разницу можно находу вычислять и записывать в вектор, а не создавать 2 разных вектора:
C++
1
2
3
4
5
6
7
8
size_t n; cin >> n; --n;
vector<int64_t> vec(n);
int64_t prev; cin >> prev;
for (size_t j = 0; j < n; ++j) {
    int64_t curr; cin >> curr;
    vec[j] = abs(curr - prev);
    prev = curr;
}
Вектор a выносите за пределы цикла и резервируете место
C++
1
2
vector<int64_t> a;
a.reserve(vec.size() - 1);
Не нужно копировать второй вектор в первый, нужно просто обменять их содержимое
C++
1
2
3
4
} else {
    vec.swap(a);
    a.clear();
}
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12942 / 6809 / 1821
Регистрация: 18.10.2014
Сообщений: 17,234
11.05.2024, 17:04
Цитата Сообщение от Bleach163 Посмотреть сообщение
Не нужно копировать второй вектор в первый, нужно просто обменять их содержимое
Можно было просто сделать перемещающее присваивание, а не какие-то притянутые за уши применения assign или swap.

C++
1
2
vec = std::move(a);
a.clear()
Хотя, конечно, многое может зависеть от реализации...

Цитата Сообщение от Artem Ka Посмотреть сообщение
Этот код тоже не проходит
"Не проходит" по какой причине???
0
458 / 294 / 191
Регистрация: 23.06.2018
Сообщений: 678
11.05.2024, 17:23
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Можно было просто сделать перемещающее присваивание, а не какие-то притянутые за уши применения assign или swap.
После чего один из буферов умрёт и его придётся заново пересоздавать на следующей итерации.
А при swap+clean у нас остаются те же самые 2 буфера, один из которых можно спокойно заново заполнить.
Хотя я сейчас погуглил, resize тоже не удаляет буфер если новый размер меньше текущего, значит можно даже его использовать вместо clean'а, чтобы push_back не проверял каждый раз переполнение текущего буфера.
0
 Аватар для lemegeton
4903 / 2696 / 921
Регистрация: 29.11.2010
Сообщений: 5,783
11.05.2024, 21:59
Можно избавиться от каунта, запихав, как у меня, флаг "все единицы".
Цитата Сообщение от Artem Ka Посмотреть сообщение
if (count(a.begin(), a.end(), 1) == a.size()){
                cout << x - a.size() << "\n";
                break;
Может быть постоянная реаллокация так тормозит.

Можно переиспользовать вектор, чтоб не занималась/освобождалась память:
Цитата Сообщение от Artem Ka Посмотреть сообщение
vector<long long> a;
Размеры всех векторов известны -- воспользуйтесь a.reserve().

Но скорее всего, ожидается алгоритм с меньшей сложностью.
Возможно, стоит обратить внимание на факторизующий алгоритм уважаемого TheCalligrapher.
0
0 / 0 / 0
Регистрация: 25.11.2022
Сообщений: 19
14.05.2024, 18:00  [ТС]
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
вариант с факторизацией каждой разницы соседних
Написал код под входные данные по вашему.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#include <cassert>
#include <utility>
#include <vector>
#include <algorithm>
#include <iostream>
using  namespace std;
std::vector<unsigned> unique_factors(unsigned v)
{
  std::vector<unsigned> r;
 
  for (unsigned d = 2; d * d <= v; ++d)
    if (v % d == 0)
    {
      r.push_back(d);
      for (v /= d; v % d == 0; v /= d);
    }
 
  if (v != 1)
    r.push_back(v);
 
  assert(std::is_sorted(r.begin(), r.end()));
  return r;
}
 
int main() 
{ 
  const unsigned MIN = 1, MAX = 100000;
  std::vector<bool> b(MAX - MIN);
  
  unsigned n;
  cin >>n;
  std::vector<unsigned> a(n);
  for (unsigned &v : a)
  {
      int x ; cin >> x;
    do v = x; while (b[v - MIN]);
    b[v - MIN] = true;
  }
 
  std::vector<std::pair<unsigned, unsigned>> curr_factors;
  unsigned n_max_length = 0, i_max_start, max_factor;
 
  for (unsigned i = 1; i < n; ++i)
  {
    unsigned diff = a[i] > a[i - 1] ? a[i] - a[i - 1] : a[i - 1] - a[i];
    auto factors = unique_factors(diff);
    auto it_curr = curr_factors.begin();
    auto it_new = factors.begin();
    while (it_curr != curr_factors.end() && it_new != factors.end())
      if (*it_new < it_curr->first)
      { // New run begins
        it_curr = curr_factors.emplace(it_curr, *it_new, i);
        ++it_new;
        ++it_curr;
      }
      else if (*it_new > it_curr->first)
      { // Existing run ends
        unsigned n_length = i - it_curr->second;
        if (n_length > n_max_length)
        {
          n_max_length = n_length;
          i_max_start = it_curr->second;
          max_factor = it_curr->first;
        }
 
        it_curr = curr_factors.erase(it_curr);
      }
      else
      { // Existing run continues
        ++it_new;
        ++it_curr;
      }
 
    // Process remaining tails, if any
 
    if (it_new != factors.end())
    {
      for (; it_new != factors.end(); ++it_new)
        // New run begins
        curr_factors.emplace_back(*it_new, i);
    }
    else
    {
      for (auto it = it_curr; it != curr_factors.end(); ++it)
      { // Existing run ends
        unsigned n_length = i - it->second;
        if (n_length > n_max_length)
        {
          n_max_length = n_length;
          i_max_start = it_curr->second;
          max_factor = it_curr->first;
        }
      }
 
      curr_factors.erase(it_curr, curr_factors.end());
    }
 
    assert(std::is_sorted(curr_factors.begin(), curr_factors.end()));
  }
 
  std::cout << n_max_length + 1 << std::endl;
  std::cout << std::endl;
 
  std::cout << max_factor << std::endl;
  for (unsigned i = i_max_start - 1; i < i_max_start + n_max_length; ++i)
    std::cout << a[i] << " ";
  std::cout << std::endl;
}
на входные данные
5
1 5 2 4 6
выдает
2
1 5
подскажите что к чему?что делать с элементами дальше?
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12942 / 6809 / 1821
Регистрация: 18.10.2014
Сообщений: 17,234
14.05.2024, 20:37
Цитата Сообщение от Artem Ka Посмотреть сообщение
подскажите что к чему?
Мой код выдает следующее: длину максимального братства.
Затем через пустую строку дополнительно: делитель, при котором получается одинаковый остаток
Затем само братство.

По приведенному вам выводу видно, что как ни трудно в это поверить мой код содержит грубую ошибку: он забывает обработать братство, простирающееся до конца последовательности. Также, еще одна ошибка: в строках 89-90 должен использоваться it, а не it_curr.

Подправленная версия кода выглядит так

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#include <cassert>
#include <utility>
#include <vector>
#include <algorithm>
#include <iostream>
 
std::vector<unsigned> unique_factors(unsigned v)
{
  std::vector<unsigned> r;
 
  for (unsigned d = 2; d * d <= v; ++d)
    if (v % d == 0)
    {
      r.push_back(d);
      for (v /= d; v % d == 0; v /= d);
    }
 
  if (v != 1)
    r.push_back(v);
 
  assert(std::is_sorted(r.begin(), r.end()));
  return r;
}
 
int main() 
{ 
  const unsigned MIN = 1, MAX = 100000;
  std::vector<bool> b(MAX - MIN);
 
  unsigned n = 100;
  std::vector<unsigned> a(n);
  for (unsigned &v : a)
  {
    do v = MIN + std::rand() % (MAX - MIN); while (b[v - MIN]);
    b[v - MIN] = true;
  }
 
  std::vector<std::pair<unsigned, unsigned>> curr_factors;
  unsigned n_max_length = 0, i_max_start, max_factor;
 
  for (unsigned i = 1; i < n; ++i)
  {
    unsigned diff = a[i] > a[i - 1] ? a[i] - a[i - 1] : a[i - 1] - a[i];
    auto factors = unique_factors(diff);
 
    auto it_curr = curr_factors.begin();
    auto it_new = factors.begin();
    while (it_curr != curr_factors.end() && it_new != factors.end())
      if (*it_new < it_curr->first)
      { // New run begins
        it_curr = curr_factors.emplace(it_curr, *it_new, i);
        ++it_new;
        ++it_curr;
      }
      else if (*it_new > it_curr->first)
      { // Existing run ends
        unsigned n_length = i - it_curr->second;
        if (n_length > n_max_length)
        {
          n_max_length = n_length;
          i_max_start = it_curr->second;
          max_factor = it_curr->first;
        }
 
        it_curr = curr_factors.erase(it_curr);
      }
      else
      { // Existing run continues
        ++it_new;
        ++it_curr;
      }
 
    // Process remaining tails, if any
 
    if (it_new != factors.end())
    {
      for (; it_new != factors.end(); ++it_new)
        // New run begins
        curr_factors.emplace_back(*it_new, i);
    }
    else
    {
      for (auto it = it_curr; it != curr_factors.end(); ++it)
      { // Existing run ends
        unsigned n_length = i - it->second;
        if (n_length > n_max_length)
        {
          n_max_length = n_length;
          i_max_start = it->second;
          max_factor = it->first;
        }
      }
 
      curr_factors.erase(it_curr, curr_factors.end());
    }
 
    assert(std::is_sorted(curr_factors.begin(), curr_factors.end()));
  }
 
  for (auto it = curr_factors.begin(); it != curr_factors.end(); ++it)
  { // Existing run ends
    unsigned n_length = n - it->second;
    if (n_length > n_max_length)
    {
      n_max_length = n_length;
      i_max_start = it->second;
      max_factor = it->first;
    }
  }
 
  std::cout << n_max_length + 1 << std::endl;
  std::cout << std::endl;
 
  std::cout << max_factor << std::endl;
  for (unsigned i = i_max_start - 1; i < i_max_start + n_max_length; ++i)
    std::cout << a[i] << " ";
  std::cout << std::endl;
}
Вывод для { 1, 5, 2, 4, 6 } выглядит так

Code
1
2
3
4
3
 
2
2 4 6
В коде, как видите, много повторений, т.е. все это можно реализовать элегантнее/компактнее. Но идею он иллюстрирует.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
14.05.2024, 20:37
Помогаю со студенческими работами здесь

Найти индекс наибольшего числа в массиве
1. Вводим неск чисел.Найти индекс наибольшего числа в массиве. Если таких чисел несколько найти индекс первого из них.

Найти в массиве из 5-ти переменных сумму наименьшего и наибольшего элементов
1. Найти в массиве из 5-ти переменных сумму наименьшего и наибольшего элементов. а) 0, 8, -8, 6, 5 б) -3, 5, 2, 11, 8 в) 3, 11, 14, ...

Найти все простые числа, оптимизация кода
Добрый день! Написал такой код: #include &lt;iostream&gt; #include &lt;string&gt; using namespace std; int main() { string sPrime =...

Необходимо найти в одномерном массиве: индексы наибольшего и наименьшего элементов
Нужно наполнить одномерный массив с помощью функции рандомных чисел, вывести его на экран и найти в нём индексы наибольшего и наименьшего...

В одномерном массиве А(10)найти значение и индекс наибольшего из отрицательных элементов.
массив random, выводить значение и индекс наибольшего из отрицательных элементов.


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
14
Ответ Создать тему
Новые блоги и статьи
Как дизайн сайта влияет на конверсию: 7 решений, которые реально повышают заявки
Neotwalker 08.03.2026
Многие до сих пор воспринимают дизайн сайта как “красивую оболочку”. На практике всё иначе: дизайн напрямую влияет на то, оставит человек заявку или уйдёт через несколько секунд. Даже если у вас. . .
Модульная разработка через nuget packages
DevAlt 07.03.2026
Сложившийся в . Net-среде способ разработки чаще всего предполагает монорепозиторий в котором находятся все исходники. При создании нового решения, мы просто добавляем нужные проекты и имеем. . .
Модульный подход на примере F#
DevAlt 06.03.2026
В блоге дяди Боба наткнулся на такое определение: В этой книге («Подход, основанный на вариантах использования») Ивар утверждает, что архитектура программного обеспечения — это структуры,. . .
Управление камерой с помощью скрипта OrbitControls.js на Three.js: Вращение, зум и панорамирование
8Observer8 05.03.2026
Содержание блога Финальная демка в браузере работает на Desktop и мобильных браузерах. Итоговый код: orbit-controls-threejs-js. zip. Сканируйте QR-код на мобильном. Вращайте камеру одним пальцем,. . .
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip Сканируйте QR-код на мобильном и вы увидите, что появится джойстик для управления главным героем. . . .
Реалии
Hrethgir 01.03.2026
Нет, я не закончил до сих пор симулятор. Эта задача сложнее. Не получилось уйти в плавсостав, но оно и к лучшему, возможно. Точнее получалось - но сварщиком в палубную команду, а это значит, в моём. . .
Ритм жизни
kumehtar 27.02.2026
Иногда приходится жить в ритме, где дел становится всё больше, а вовлечения в происходящее — всё меньше. Плотный график не даёт вниманию закрепиться ни на одном событии. Утро начинается с быстрых,. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru