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

Регистрация
4 Фев 2013
Сообщения
98
Репутация
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) максимально.



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

Можно использовать ассоциативный массив (также известный как словарь или хеш-таблица) для хранения уже вычисленных значений функции 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)
 
Для того чтобы найти максимальное значение функции 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.
 
Значение F(n) равно количеству единичных битов в числе n.
Таким образом, надо взять ближайшее большее 1000000000 число вида 2 ** t - 2 и последовательно сдвигать в нём нулевой бит: от бита номер 0 влево - пока очередное число окажется не больше 1000000000. const unsigned long max = 1000000000UL;
unsigned long t = (1UL
 
Назад
Сверху