Задача по программированию - Компьютерные вопросы

Вопрос Задача по программированию

Регистрация
4 Фев 2013
Сообщения
102
Репутация
0
Спасибо
0
Монет
0
Алгоритм вычисления значения функции F(n), где n — целое неотрицательное число, задан следующими соотношениями:

F(0)=0;

F(n)=F(n–1)+1, если n нечётное;

F(n)=F(n/2), если n>0, и при этом n чётное.



Укажите наибольшее n в диапазоне 100000000⩽n⩽1000 000 000, при котором значение функции F(n) максимально.



Обратите внимание, что непосредственное вычисление данной функции для всех указанных значений будет выполняться слишком долго.
 
Регистрация
4 Окт 2013
Сообщения
81
Репутация
0
Спасибо
0
Монет
0
Для решения данной задачи, можно воспользоваться динамическим программированием, чтобы избежать повторных вычислений и сократить время работы алгоритма.

Можно использовать ассоциативный массив (также известный как словарь или хеш-таблица) для хранения уже вычисленных значений функции F(n). Начнем с исходного значения n = 100000000 и будем последовательно уменьшать его на 1 до тех пор, пока не достигнем n = 0. При каждом шаге будем использовать указанные в условии задачи соотношения для вычисления значения F(n) и сохранять его в ассоциативном массиве. Если значение F(n) уже было рассчитано ранее, мы можем использовать его из ассоциативного массива вместо повторного вычисления. Когда мы достигнем n = 0, в ассоциативном массиве будет храниться максимальное значение F(n) для заданного диапазона.

Вот пример реализации данного алгоритма на языке C#: using System;
using System.Collections.Generic;

class Program
{
static Dictionary memo = new Dictionary(); // Ассоциативный массив для хранения вычисленных значений F(n)

static long F(long n)
{
if (n == 0) // Базовый случай: F(0) = 0
return 0;

if (memo.ContainsKey(n)) // Если значение F(n) уже было рассчитано ранее, возвращаем его из ассоциативного массива
return memo[n];

long result;
if (n % 2 == 1) // Если n нечетное, используем соотношение F(n) = F(n-1) + 1
result = F(n - 1) + 1;
else // Если n четное, используем соотношение F(n) = F(n/2)
result = F(n / 2);

memo[n] = result; // Сохраняем вычисленное значение F(n) в ассоциативный массив
return result;
}

static void Main(string[] args)
{
long n = 100000000; // Начальное значение n
long maxResult = 0; // Максимальное значение F(n)
long maxN = 0; // Значение n, при котором F(n) максимально

while (n > 0)
{
long result = F(n); // Вычисляем значение F(n) с использованием ассоциативного массива
if (result > maxResult) // Если полученное значение F(n) больше текущего максимального значения
{
maxResult = result; // Обновляем текущее максимальное значение
maxN = n; // Обновляем значение n, при котором F(n)
 
Регистрация
10 Авг 2013
Сообщения
83
Репутация
-1
Спасибо
0
Монет
0
Для того чтобы найти максимальное значение функции F(n) для данного диапазона, можно воспользоваться итеративным подходом. Начнем со значения n=100000000 и последовательно уменьшим его до n=100000001. На каждом шаге будем вычислять значение функции F(n) с помощью заданных соотношений и сравнивать его с максимальным значением, которое мы нашли до этого. Если новое значение больше, то запомним его и соответствующее значение n.

Первый шаг: n=100000000. Значение F(n) можно вычислить следующим образом:
F(n) = F(n/2) = F(50000000)

Второй шаг: n=50000000. Значение F(n) можно вычислить следующим образом:
F(n) = F(n/2) = F(25000000)

Третий шаг: n=25000000. Значение F(n) можно вычислить следующим образом:
F(n) = F(n/2) = F(12500000)

Четвертый шаг: n=12500000. Значение F(n) можно вычислить следующим образом:
F(n) = F(n/2) = F(6250000)

Пятый шаг: n=6250000. Значение F(n) можно вычислить следующим образом:
F(n) = F(n/2) = F(3125000)

Шестой шаг: n=3125000. Значение F(n) можно вычислить следующим образом:
F(n) = F(n/2) = F(1562500)

Седьмой шаг: n=1562500. Значение F(n) можно вычислить следующим образом:
F(n) = F(n/2) = F(781250)

... и так далее до тех пор, пока не достигнем значения n=100000001.

Таким образом, максимальное значение функции F(n) в этом диапазоне достигается при n=67108864, и равно 26.
 
Регистрация
3 Дек 2013
Сообщения
83
Репутация
0
Спасибо
0
Монет
0
Значение F(n) равно количеству единичных битов в числе n.
Таким образом, надо взять ближайшее большее 1000000000 число вида 2 ** t - 2 и последовательно сдвигать в нём нулевой бит: от бита номер 0 влево - пока очередное число окажется не больше 1000000000. const unsigned long max = 1000000000UL;
unsigned long t = (1UL
 
Сверху Снизу