Условие задачи:
http://www.e-olimp.com.ua/problems/3
Прохождение тестов данной программой:
http://www.e-olimp.com.ua/
solutions/1591163
Ввод | Вывод | Комментарий | Вердикт |
0 | 0 | Проверка на нуль: | Пройдено |
3 | 28 | Тот же пример что и в условии к задаче: Сходится | Проверка пройдена |
9 | 62 | 1 этап | Пройдено |
13 | 83 | 2 этап | Пройдено |
19 | 112 | 3 этап | Пройдено |
2Е9 | 6.00953Е9 | Проверка на переполнение максимальным возможным числом: | Пройдено |
Вначале увидев эту задачу я понял что самое главное в этой задаче это понять какую фигуру лучше строить и как строить. С фигурой все было очевидно: в данном случае самая экономичная фигура это куб, а это значит что нам нужно найти как лучше всего его строить, а если быть более точным как из кубов с величиной стены [latex]I[/latex] построить куб с величиной стены [latex]I+1[/latex]. Я решил что нужно последовательно наращивать стены: вначале боковую, потом верхнюю и напоследок заднюю. Здесь было замечено что количество кубов входящих в нашу фигуру можно найти просто возведя сторону в кубическую степень, с этого и пошли эти строчки:
13 14 15 |
for(; k<n ; ++i){ k=pow(i+1,3); } |
Вот таким незамысловатым способом мы нашли величину стены у куба если он закончен. Что ж давайте теперь найдем в каком этапе находится строительство куба:
Первый этап(строительство боковой стены):
18 |
if ( (i-1)*(i-1)*(i-1) < n && n<= (i-1)*(i-1)*i ) |
Второй этап(строительство верхней стены):
23 |
else if ( (i-1)*(i-1)*i < n && n<= (i-1)*i*i ) |
Или третий(строительство задней стены):
28 |
else if ( (i-1)*i*i < n && n<= i*i*i ) |
[latex]3xyz+2xy+2xz+2yz+x+y+z[/latex] и из неё я уже вывел эти формулы:
1) Если все стороны равны: [latex]3n(n+1)^2[/latex];
20 |
r=3*(i-1)*pow(i,2); |
2) Если две стороны равны, а третья на единицу больше: [latex]3n^3 + 9n^2 + 7n + 1[/latex];
25 |
r= 3*pow(i-1,3) + 9*pow(i-1,2) + 7*(i-1) + 1; |
3) Если две стороны равны, а третья на единицу меньше: [latex]3n^3 + 3n^2 -n-1[/latex].
30 |
r= 3*(pow(i,3) + pow(i,2))-i-1; |
Зачем? Первая формула пригодится нам для первого этапа, когда к уже готовому кубу добавляются еще кубы. Вторая: когда после первого этапа одна сторона стала больше чем остальные. И конечно же третья: которая соответственно строится когда две стороны больше третьей.
Теперь нам осталось только достроить недостающие кубы, для этого вначале нужно узнать сколько кубов нужно достроить:
1)Для первого этапа:
21 |
n-=pow(i-1,3); |
2)Для второго:
26 |
n-=pow(i-1,2)*i; |
3)И конечно же для третьего:
31 |
n-=pow(i,2)*(i-1); |
Далее нам нужно их построить, здесь все тоже просто они строятся как же как и квадратные числа, всё что нам нужно сделать это найти сколько нужно добавить спичек чтобы достроить еще один куб и когда. Так вот, достройка делается через треугольные числа. Поэтому создается цикл который выдает треугольные числа по порядку и вложенный в него цикл, который проходит все эти треугольные числа:
37 |
for( int i1=1 ; n ; i1+=2 )for( int i2=0 ; i2<i1 && n ; i2++,n-- ) |
3 | 3 | 3 | 5 |
3 | 3 | 5 | 3 |
3 | 5 | 3 | 3 |
8 | 5 | 5 | 5 |
и в таком порядке:
16 | 15 | 14 | 13 |
9 | 8 | 7 | 12 |
4 | 3 | 6 | 11 |
1 | 2 | 5 | 10 |
Как вы видите +8 мы видим только на первом кубе, а +5 на первом кубе треугольного и в середине треугольного . Осталось только описать это и мы получаем:
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 |
#include <cstdlib> #include <iostream> #include <cmath> using namespace std; int main() { double n, k=1, i=0,r,r1; cin>>n; for(; k<n ; ++i){ k=pow(i+1,3); } if(!i)i++; if ( (i-1)*(i-1)*(i-1) < n && n<= (i-1)*(i-1)*i ) { r=3*(i-1)*pow(i,2); // 3n(n+1)^2 n-=pow(i-1,3); } else if ( (i-1)*(i-1)*i < n && n<= (i-1)*i*i ) { r= 3*pow(i-1,3) + 9*pow(i-1,2) + 7*(i-1) + 1; // 3n^3 + 9n^2 + 7n + 1 n-=pow(i-1,2)*i; } else if ( (i-1)*i*i < n && n<= i*i*i ) { r= 3*(pow(i,3) + pow(i,2))-i-1; // 3n^3 + 3n^2 -n-1 n-=pow(i,2)*(i-1); } else{ cout << i << "???"; return 0; } for( int i1=1 ; n ; i1+=2 ) { for( int i2=0 ; i2<i1 && n ; i2++,n-- ) { if( i1 == 1 ){ r+=8; } else if( i2 == 0 || i2 == i1/2 ){ r+=5; } else{ r+=3; } } } cout << r << endl; return 0; } |
Очень хорошо, что удалось решить эту задачу! Молодец!
— по возможности поправьте орфографию и стилистику
— ссылку на e-olimp с задачей и пройденными тестами, разместите, пожалуйста в самом начале. И лучше просто две ссылки без пояснений.
Спасибо, я исправил недочеты(те которые были мной замечены) и разместил ссылки в самом начале задачи
— Когда вставляете в текст строки программы отдельно от самой программы, нужно оставлять тот же номер строки. Это позволяет найти место в программе откуда взята строка. Сделать это можно если в разделе «Нумерация» заполнить поле «Начать с».
Сейчас у всех номер 1. Сбивает.
— С отступами нужно что-то делать. И в 34-й строке endl должен быть.
— Для возведения целого числа в квадрат или куб функцию pow() использовать не следует.
— Для вычисления кубического корня следует использовать функцию pow() а не цикл перебора.