Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Вычисление ряда уникальных чисел по формулам 
:(
    Опции темы
dershokus
Дата 12.11.2012, 17:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 82
Регистрация: 7.8.2011

Репутация: нет
Всего: 1



Снова здравствуйте smile
Нужно напечатать 1000 неповторяющихся чисел в порядке возрастания из множества M:
1. единица принадлежит к множеству M
2. к множеству M принадлежит число 2*x+1 (х - принадлежит множеству М)
3. к множеству М принадлежит число 3*х+1 (х - принадлежит множеству М)
Конечно можно просто посчитать все, отсортировать и вычеркнуть одинаковые и если не достаточно чисел - повторить процесс, но может можно как-то легче?

PM MAIL   Вверх
Фантом
Дата 12.11.2012, 19:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Вы это прекратите!
***


Профиль
Группа: Участник Клуба
Сообщений: 1516
Регистрация: 23.3.2008

Репутация: 2
Всего: 49



Чего-то в Вашем условии явно не хватает. В его рамках ряд чисел a(n)=2*a(n-1)+1, a(0)=1 будет ответом, но, наверное, хочется получить что-то другое?
PM   Вверх
DarkProg
Дата 12.11.2012, 19:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Законченный романтик
***


Профиль
Группа: Завсегдатай
Сообщений: 1784
Регистрация: 11.3.2009
Где: Земля

Репутация: нет
Всего: 19



Эмм... я может чего-то упускаю, но выглядит как-то просто что ли...

1, потом берёте 1 подставляете в две формулы, результаты помещаете в массив, и т.д. проверяя каждый раз чтобы не было дублей, потом берёте числа которые новые подставляете  их и т.д.

А вообще чего-то я не улавливаю числа отличного от 0, в котором бы эти функции дали одинаковый результат... учитывая что это уравнение двух прямых...

Чисто как вариант я бы попробовал бы на бумаге вычислить закономерность для общего рада... мне кажется она будет и тогда решение станет ещё элегантнее, но в лоб мне такое например не далось...а может я ошибаюсь...

А вообще просто обратите внимание на то что у вас два ряда и у одного коэффициент больше, это значит что все его значения всегда будут больше, и значит его надо вычислять всегда вторым и следовательно не будет нужды в сортировке.
Т.е. нм мой взгляд нечто такое
1) 1 подставляет в 1-ю ф-цию, потом во вторую
2) полученный результат по очередно в первую функцию, потом во вторую.
3) результат предыдущего шага опять же в 1-ю функцию, потом во вторую.

Обратите внимание на то как растёт последовательность в плане количества членов и можно будет точно отсчитать момент останова по количеству новых членов, не считая полного количества элементов.

Добавлено через 2 минуты и 51 секунду
Цитата(Фантом @  12.11.2012,  20:12 Найти цитируемый пост)
В его рамках ряд чисел a(n)=2*a(n-1)+1, a(0)=1 будет ответом, но, наверное, хочется получить что-то другое? 

Эмм, а тут точно нет ошибки, на первом шаге должно получиться 2 числа - 3 и 4?


--------------------
"И твоя голова всегда в ответе за то куда сядет твой зад..."

"Я студент - скажите с какого я ВУЗа..."

 smile  smile  smile 
PM MAIL   Вверх
Фантом
Дата 12.11.2012, 19:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Вы это прекратите!
***


Профиль
Группа: Участник Клуба
Сообщений: 1516
Регистрация: 23.3.2008

Репутация: 2
Всего: 49



Цитата(DarkProg @  12.11.2012,  20:30 Найти цитируемый пост)
учитывая что это уравнение двух прямых...

Зависимости рекуррентные, так что это не две прямые. К тому же, насколько я понимаю, никак не возбраняется "переключаться" с одной зависимости на другую.

Другое дело, что, как я уже писал, тут явно не хватает какого-то условия. Например, того, что надо напечатать 1000 наименьших неповторяющихся чисел.
PM   Вверх
dershokus
Дата 12.11.2012, 20:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 82
Регистрация: 7.8.2011

Репутация: нет
Всего: 1



Цитата

надо напечатать 1000 наименьших неповторяющихся чисел

да. я написал в порядке возрастания. можно с любого элемента начинать, просто проше всего начинать с 1.
Ряд сначала получается 1 3 4 7 9 10... Тоесть мы получаем из 1 элемента - 2.  
Но если сначала считать первую формулу для 3 а потом для 4 (на первом просчете) а потом второую формулу для них - мы не получим упорядоенный ряд. (реализация на работе, завтра отправлю первые .... много чисел из этого ряда).
Если на некотором просчете мы получили N чисел из которых мы должны получить 2*N (по двум формулам), то в 2*N числах могут быть такие, которые меньше чем числа из N.
Что-то витьевато выражаюсь, за что извиняюсь smile 
PM MAIL   Вверх
Akina
Дата 12.11.2012, 21:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 20
Всего: 454



Код

X=1;
Y=X;
Z=0;
Понеслася
  Если X>Y
    Печатаем Y;
    Y=Y*3+1;
  А если X<Y
    Печатаем X;
    X=X*2+1;
  Иначе
    Печатаем Y;
    Y=Y*3+1;
    X=X*2+1;
  Закончили с Если;
  Z=Z+1;
Хреначим пока Z<1000;
Всё собсно.



--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
Фантом
Дата 12.11.2012, 21:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Вы это прекратите!
***


Профиль
Группа: Участник Клуба
Сообщений: 1516
Регистрация: 23.3.2008

Репутация: 2
Всего: 49



Цитата(dershokus @  12.11.2012,  21:58 Найти цитируемый пост)

да. я написал в порядке возрастания. можно с любого элемента начинать, просто проше всего начинать с 1.

Мое первое "решение" тоже будет выдавать числа в порядке возрастания.  smile 

Ну ладно, кажется, я понял, что требуется. Тогда проще просто пройтись по натуральным числам подряд, проверяя, можно ли получить очередное из уже существующих в ряду. 

Выглядеть это будет примерно так (поскольку я не знаю, на каком языке это нужно реализовывать, написал на Паскале, для описания алгоритма это проще)
Код

program e2x3x;
  var 
  A : array[1..10000] of boolean;
  i,n : integer;
        
  begin
    
    A[1]:=true;
    writeln(1);
    n:=1;
        
    for i:=2 to 10000 do  begin
        A[i]:=(((i-1) mod 3 =0) and A[(i-1) div 3]) or (((i-1) mod 2 =0) and A[(i-1) div 2]);
        if A[i] then begin
          writeln(i);
          inc(n)
        end;    
        if n=1000 then break
    end
end.

Здесь n - счетчик накопившегося количества чисел, размер 10000 взят "с запасом", чтобы наверняка хватило.

PM   Вверх
dershokus
Дата 13.11.2012, 09:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 82
Регистрация: 7.8.2011

Репутация: нет
Всего: 1



Akina, Вы не правы. Ваш алгоритм не просчитываем числа из множества.
Ряд такой получается:
Код

1, 3, 4, 7, 9, 10, 13, 15, 19, 21, 22, 27, 28, 31, 31, 39, 40, 43, 45, 46, 55, 57, 58, 63, 63, 64, 67, 79, 81, 82

по вашему алгоритму
Код

1, 3, 4, 7, 13, 15, 31, 40, 63, 121, 127, 255, 364,

PM MAIL   Вверх
Akina
Дата 13.11.2012, 10:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 20
Всего: 454



dershokus, само собой, я же не учитываю ветвления.
Но идея может быть использована. Правда, потребуется не два аккумулятора, а динамически расширяемый массив аккумуляторов. Из которого берётся наименьший элемент, печатается, затем на его основе генерится и помещается в массив 2 новых значения, а обработанное значение выбрасывается.

Это сообщение отредактировал(а) Akina - 13.11.2012, 10:59


--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
Silent
Дата 14.11.2012, 10:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 252
Регистрация: 3.10.2006

Репутация: 1
Всего: 9



Простейший вариант - взять очередь с приоритетами, в две минуты пишется код:
Код

#include <stdio.h>
#include <queue>
using namespace std;

struct compare  
{  
  bool operator()(const int& l, const int& r)  
  {  
      return l > r;  
  }  
};    

priority_queue <int, vector<int>, compare> M;

int main()
{
    M.push(1);
    for (int i = 1; i <= 1000; i++)
    {
        int x = M.top();
        M.pop();
        M.push(2*x+1);
        M.push(3*x+1);
        printf("%d ", x);
    }
    return 0;
}


Ну а если еще чуть подумать, то становится ясно, что это стрельба по воробьям из пушки, и гораздо проще идея, предложенная Фантомом, сделать простой перебор:
Код

#include <stdio.h>

int main()
{
    int count = 0;
    for (int i = 1; count <= 1000; i++)
        if ((i == 1) || ((i-1) % 2 == 0) || ((i-1) % 3 == 0))
        {
            printf("%d ",i);
            count++;
        }
    return 0;



Я бы стал сдавать код №2 - проще, быстрее, никакого расхода памяти
PM MAIL   Вверх
Фантом
Дата 14.11.2012, 11:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Вы это прекратите!
***


Профиль
Группа: Участник Клуба
Сообщений: 1516
Регистрация: 23.3.2008

Репутация: 2
Всего: 49



Цитата(Silent @  14.11.2012,  11:43 Найти цитируемый пост)

Я бы стал сдавать код №2 - проще, быстрее, никакого расхода памяти 

Вы забыли одну важную деталь (учет которой, собственно, и приводит к расходу памяти): по условию, числа 2*x+1 и 3*x+1 принадлежат M в том случае, если x принадлежит M (а не является целым числом, как у Вас). Первое отличие - число 5. Оно, конечно, нечетное, но подходящего для него x не существует.

К тому же Ваш вариант (если уж пользоваться измененным условием задачи) можно сильно упростить. Наименьшее общее кратное 2 и 3 равно 6, поэтому код
Код

#include <stdio.h>
int main()
{
    for (int i = 0; i < 1000; i+=6)
         printf("%d %d %d %d ",i+1,i+3,i+4,i+5);
    return 0;
}

будет выдавать такой же результат.  smile 
PM   Вверх
Silent
Дата 14.11.2012, 12:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 252
Регистрация: 3.10.2006

Репутация: 1
Всего: 9



Каюсь, со вариантом №2 просчитался - слишком поверхностно посмотрел Ваш код. Тем не менее, у меня еще есть второй вариант, который №1 smile
PM MAIL   Вверх
Фантом
Дата 14.11.2012, 21:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Вы это прекратите!
***


Профиль
Группа: Участник Клуба
Сообщений: 1516
Регистрация: 23.3.2008

Репутация: 2
Всего: 49



Цитата(Silent @  14.11.2012,  13:34 Найти цитируемый пост)
Тем не менее, у меня еще есть второй вариант, который №1

Это да, но всерьез пользоваться возможностями C++, если явно не оговорено, что это можно, как-то нехорошо.  smile Я сначала тоже успел подумать, что мне больше нравится для этой задачи, Lua или Prolog, и только потом решил, что ТС я этим никак не помогу, после чего сменил язык на наиболее банальный.
PM   Вверх
volatile
Дата 15.11.2012, 04:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 2
Всего: 85



Код

#include <set>

void series (int cnt)
{
    std::set <int> a;
    a.insert (0);

    while (cnt --> 0)
    {
        int x = * a.begin () + 1;
        a.erase (a.begin ());
        a.insert (2 * x);
        a.insert (3 * x);
        std::cout << x << ' ';
    }
}

http://codepad.org/FKQFn95I

Добавлено через 5 минут и 35 секунд
без повторов же надо.
Цитата(dershokus @  12.11.2012,  17:29 Найти цитируемый пост)
1000 неповторяющихся чисел 

это без повторов.

Добавлено через 11 минут и 58 секунд

Цитата(Фантом @  14.11.2012,  21:40 Найти цитируемый пост)
пользоваться возможностями C++ ... как-то нехорошо

оу, сорри.
паскакалей не знаем.

PM MAIL   Вверх
Silent
Дата 15.11.2012, 08:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 252
Регистрация: 3.10.2006

Репутация: 1
Всего: 9



Цитата(Фантом @  14.11.2012,  21:40 Найти цитируемый пост)
Это да, но всерьез пользоваться возможностями C++, если явно не оговорено, что это можно, как-то нехорошо.

я такого пункта от автора топика не увидел, укажите, если я не прав (хотя, конечно, и не сказано про язык реализации).
Тогда предлагаю кросс-языковый вариант (предполагаю, что можно использовать хотя бы массивы):
Код

#include <stdio.h>

const int N = 1000;
int M[N];
int head = 0,
    tail = 0;

void push(int x)
{
    int i;
    for (i = tail - (tail == N-1); (i > 0) && (M[i] > x); i--)
        M[i+1] = M[i];
    if (i < N) M[i+1] = x;
    tail++;
}

bool find(int x, int l, int r)
{
    int mid;
    if (M[r] < x ) return false;
    while (l < r)
    {
        mid = l + (r-l) / 2;
        if (x <= M[mid]) r = mid;
        else l = mid + 1;
    }
    if (M[r] == x) return true;
    else return false;
}

int main()
{
    M[0] = 1;
    while (tail < N)
    {
        int x = 2 * M[head] +1;
        if (!find(x,0,tail)) 
            push(x);
        int y = 3 * M[head] + 1;
        if (!find(y,0,tail)) push(y);
        head++;
    }
    for (int i = 0; i < N; i++) printf("%d ",M[i]);
    return 0;
}

PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Алгоритмы"

maxim1000

Форум "Алгоритмы" предназначен для обсуждения вопросов, связанных только с алгоритмами и структурами данных, без привязки к конкретному языку программирования и/или программному продукту.


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, maxim1000.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Алгоритмы | Следующая тема »


 




[ Время генерации скрипта: 0.0595 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.