Прості задачі з підготовки до олімпіади

Трикутники

Білі кубики

Трикутники

Михайлик любив малювати трикутники, але він це робив у незвичний спосіб. Спочатку малював довільний трикутник, потім кожну сторону ділив на n рівних частин і проводив через точки поділу прямі, паралельні сторонам трикутника. У результаті виходить декілька рівних між собою трикутників. Допоможіть Михайлику знайти найбільшу кількість однакових трикутників у його фінальному рисунку.

Вхідні дані Ціле число n (0 < n < 2 * 109). Вихідні дані Вивести найбільшу кількість рівних між собою трикутників.

Розв'язок

Побудуємо трикутник і будемо добудовувати такі ж само неначе семетрично відносно вершин. Добудова кожного ряду визначає ділення сторони на число більше на одиницю від ноступного.

Ліміт часу 1 секунда Ліміт використання пам'яті 64 MiB

Вхідні дані #1 2 Вихідні дані #1 4

Ось два стовчики рядів, що утворилися

Отже розв'язування зводиться до визначення квадрата числа.

Звичайно це можна було б помітити і відразу, виконавши кілька підстановок, та чи не цікавим було дослідження виявлених числових рядів?

До речі, використовуючи у програмі числову величину типу даних integer (int) чи навіть і uint(беззнаковий тип) програма проходить 90% тестів. Тому змінну оголошуємо типу long, або ulong.

using System; class delta { private static void Main() { ulong a = Convert.ToUInt64(Console.ReadLine()); Console.WriteLine(a*a); } }

Білі кубики

Професор Самодєлкін задумав виготовити кубики з брусків білого кольору. Довжина кожного ребра дорівнює 1 дм. Після виготовлення кубиків професор вирішив зробити всі кубики також білого кольору. Скільки кубиків із стороною 1 дм зможе виготовити з одного бруска професор, та скільки сторін прийдеться йому пофарбувати, якщо відомо, що довжини сторін брусків - цілі числа і задані також в дециметрах.

Вхідні дані Один рядок містить три цілих числа – розміри бруска в дм, які не перевищують 1000000.

Вихідні дані В єдиному рядку записати через пропуск два цілих числа: кількість отриманих кубиків та кількість граней кубиків, які необхідно пофарбувати.

Ліміт часу 1 секунда  Ліміт використання пам'яті 64 MiB Вхідні дані 1 2 3 Вихідні дані 6 14

Розв'язок

Знайти кількість кубиків не складно, це добуток введених чисел. Деяку складність викликає прочитати числа введені через проміжок. Це можна зробити методом Split наприклад так:

int[] mass =Convert.ToInt32 (Console.ReadLine ().Split(' '));

class WhiteCubes { static void Main() { int[] mass =Convert.ToInt32 (Console.ReadLine ().Split(' ')); Console.WriteLine(mass[0]*mass[2]*mass[2]);

} }

Значно важче визначити скільки ж граней треба дозафарбувати у кубиках.

Нехай ми маємо брусок a x b x c де a,b,c - довжини ребер бруска

Можна будувати числові ряди і визначати закономірності їх зростання:

якщо кубик 1х1х1 то дофарбовуємо 0 граней

якщо 2х1х1 =1х2х1 =1х1х2 то 2

якщо 3х1х1 =1х3х1 =1х1х3 то 4

якщо 4х1х1 =1х4х1 =1х1х4 то 8

і т. д. Закономірність 2a*b*c-1

якщо кубик 2х2х1 (чи 1х2х2, чи 2х1х2) то дофарбуємо 8 граней

3х2х1 то 8 + 6

4х2х1 то 8 + 6 + 6

і т. д. Значення зростає на 6

якщо 2х2х2 то 8 + 8 + 8

якщо 3х2х2 то 8 + 8 + 8 + 8

якщо 4х2х2 то 8 + 8 + 8 + 8 +8

і т. д. Значення зростає на 8

У результаті такого аналізу обов'язково побудується необхідна нам модель але розв'язок можна виявити простіше вивівши певний алгебраїчний вираз.

Кожен розріз бруска перпендикулярно ребру а (параленьно грані bc) збільшує кількість фарбувань на 2bc.

Тобто кількість фарбувань при усіх розрізах паралельно грані bc складає 2bc(а-1)= 2abc-2bc

при усіх розрізах паралельно грані ac складає 2ac(b-1)= 2abc-2аc

при усіх розрізах паралельно грані ab складає 2ab(c-1)= 2abc-2ab

Загальна кількість фарбувань = 2bc(а-1)+2ac(b-1)+2ab(c-1) = 2abc-2bc+2abc-2ac+2abc-2ab =2(3abc-ab-ac-bc)

using System;

class WhiteCubes { static void Main() { int[] mass =Convert.ToInt32 (Console.ReadLine ().Split(' '));

int a = mass[0];

int b = mass[1];

int c = mass[2];

Console.WriteLine(a*b*c + " " +2*(3*a*b*c-a*b-a*c-b*c));

} }

Поїздка на екскурсію

Учні 10-Б класу, на осінні канікули, вирішили поїхати на екскурсію до столиці. Знаючи кількість хлопчиків n та дівчаток m, визначити скільки потрібно замовити кімнат в готелі, в якому є кімнати на k місць кожна, за умови, що хлопчиків та дівчаток поселяти разом заборонено.

Вхідні дані: В одному рядку записано три числа n, m, k (n, m, k ≤ 100).

Вихідні дані: Вивести одне число - кількість кімнат, які потрібно забронювати в готелі.

Ліміт часу 1 секунда.Ліміт використання пам'яті 64 MiB

Вхідні дані: 6 12 3 Вихідні: 6

Кількість кімнати для хлопчиків визначається діленням націло кількості хлопців та кількості місць у одній кімнаті плюс ще одна кімната якщо залишок від ділення не нуль. Те ж саме і для дівчат.

using System; class excursion { static void Main() { string[] mass = Console.ReadLine ().Split(' '); int n = Convert.ToInt32(mass[0]); // кількість хлопчиків int m = Convert.ToInt32(mass[1]); // кількість дівчаток int k = Convert.ToInt32(mass[2]); // кількість місць у одній кімнаті int b; // кількість кімнат b = n / k; if (n % k > 0) b = b+1; b = b + m / k; if (m % k > 0) b = b+1; Console.WriteLine(b); Console.ReadLine(); } }

Поділ скарбу (№ 6274)

Піратам вдалося справедливо розділили скарб із m золотих монет – кожен отримав частину відповідно до свого піратського рангу і стажу.

Наймолодший пірат взяв одну монету, а кожен наступний пірат брав на одну монету більше, ніж попередній його колега.

Коли останній пірат забрав свою долю, то ще лишилось n монет, які були закопані на "чорний день".

Скільки було піратів?

Вхідні дані: Два натуральних числа m та n (1 ≤ n < m ≤ 106).

Вихідні дані: Вивести кількість піратів.

Ліміт часу 1 секунда. Ліміт використання пам'яті 64 MiB

Вхідні дані: 17 2 Вихідні дані: 5

using System; class ProgramPirats { static void Main() { string [] mass= Console.ReadLine().Split( ); // зчитуються текстові значення вхідних даних у масив int m = Convert.ToInt32(mass[0]); // кількість знайдених монет int n = Convert.ToInt32(mass[1]); // кількість монет закопаних на чорний день int p = 0; // кількість піратів int a = m - n; // кількість розділених між піратами монет while (a>0) // кількість монет буде зменшуватись і цикл зупиниться коли їх не стане зовсім { p = p + 1; // "номер" пірата зростає a = a - p; // фактично пірати отримує стільки монет, який його номер по порядку

} Console.WriteLine(p); // воводимо "номер" останнього пірата, тобто їх кількість. Console.ReadKey(true); } }

Сторона квадрата (№ 1359) Знайти цілочисельну довжину сторони квадрата, який можна отримати з двох прямокутників axb та cxd, розрізавши їх на прямокутники,

а потім склавши так, щоб утворився квадрат найбільш можливої площі. Вхідні дані: У одному рядку знаходиться чотири дійсних числа a, b, c, d. Площа кожного прямокутника не перевищує 2*10^9. Вихідні дані: Вивести одне число - сторону утвореного квадрата. Ліміт часу: 1 секунда Ліміт використання пам'яті: 64 MiB Вхідні дані: 1 2 3 4 Вихідні дані: 3

Пояснення Оскільки площа прямокутників не перевищує мільярду то довжина сторони буде меншою кореня з цього числа тобто <31623. Отже вистачить

шіснадцятибітного цілого числа. У C# це short.

Площу квадрата знайти не складно, вона повинна мати обсяг не більше двох мільярдів. Для її зберігання підійде 32-бітний тип int.

Корінь є числом дійсним, яке потрібно заокруглити до цілого. Наприклад методом Math.Ceiling до найближчого цілого чи методом Math.Floor

до цілого, що не перевищує задане. Обидва методи повертають цілочисельне значення типу double.

Та код:

s = (a*b) + (c*d);

double kk = Math.Sqrt(s);

k = Math.Floor(kk);

Видасть лише 30% !

Ось уся програма невдаха:

using System;

class SQR

{

static void Main()

{

string[] mass = Console.ReadLine ().Split(' ');

int a = Convert.ToInt32(mass[0]); // сторона першого прямокутника

int b = Convert.ToInt32(mass[1]); // сторона першого прямокутника

int c = Convert.ToInt32(mass[2]); // сторона другого прямокутника

int d = Convert.ToInt32(mass[2]); // сторона другого прямокутника

int s; // площа квадрата

double k; // сторона квадрата

s = (a*b) + (c*d);

double kk = Math.Sqrt(s);

k = Math.Floor(kk);

Console.WriteLine(k);

Console.ReadLine();

}

}

Отже ми невірно зрозуміли умову! Напевно різати прямокутники можна лише на цілочисельні. Тобто заокруглювати треба

аж до квадрати з цілого числа. Один із варіантів шукати такі квадрати циклом, доки значення не перевищить площу.

using System;

class SQR

{

static void Main()

{

string[] mass = Console.ReadLine ().Split(' ');

int a = Convert.ToInt32(mass[0]); // сторона першого прямокутника

int b = Convert.ToInt32(mass[1]); // сторона першого прямокутника

int c = Convert.ToInt32(mass[2]); // сторона другого прямокутника

int d = Convert.ToInt32(mass[2]); // сторона другого прямокутника

int s = (a*b) + (c*d); // площа квадрата

double k = 1; // сторона квадрата, для початку = 1

while (k*k < s) k = k + 1;

Console.WriteLine(k-1);

// Console.WriteLine(s);

Console.ReadLine();

}

}

Та результат все ті ж 30%. Отже варто думати далі!