Нужен ваш вклад Project Euler Q 8

0

Есть ли лучший способ сделать это?

http://projecteuler.net/problem=8

Я добавил условие, чтобы проверить, есть ли число> 6 (Исключает мелкие продукты и 0)

#include <iostream>
#include <math.h>
#include "bada.h"
using namespace std;
int main()
{
    int badanum[] { DATA };
    int pro=0,highest=0;
    for(int i=0;i<=996;++i)
    {
        if (badanum[i]>6 and badanum[i+1] > 6 and badanum[i+2] >6 and badanum[i+3]>6 and badanum[i+4]>6)
        {
            pro=badanum[i]*badanum[i+1]*badanum[i+2]*badanum[i+3]*badanum[i+4];
            if(pro>highest)
            {
                cout << pro << " " << badanum[i] << badanum[i+1] << badanum[i+2] << badanum[i+3] << badanum[i+4] << endl;
                highest = pro;
            }
            pro = 0;
        }
    }
}

bada.h - это всего лишь файл, содержащий 1000-значное число.

#DEFINE DATA <1000 digit number>

http://projecteuler.net/problem=8

  • 1
    Подожди, зачем нужны дополнительные условия? Кроме того, как написано, вы уходите от конца массива. Наконец, есть еще один сайт для Code Reviews.
  • 3
    Проверка > 6 делает вашу программу неправильной. Вы не гарантированно найдете 5 последовательных цифр, все больше чем 6, и возможно, что самый большой продукт может включать цифру, меньшую или равную 6, даже если есть группа из 5 цифр, все больше чем 6.
Показать ещё 7 комментариев
Теги:
arrays

3 ответа

1

что, если замедлить на самом деле

  • вызывает ветвление параллельного конвейера выполнения ЦП
  • также как упоминалось ранее, это приведет к недействительности результата
  • не имеет значения, что ваше решение такое же, как и должно быть (для других цифр оно не могло)

С алгоритмической стороны вы можете сделать:

  1. если у вас достаточно быстрое деление, вы можете уменьшить число вычислений

    char a[]="7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450\0";
    
    int i=0,s=0,m=1,q;
    for (i=0;i<4;i++)
        {
        q=a[i  ]-'0'; if (q) m*=q;
        }
    for (i=0;i<996;i++)
        {
        q=a[i+4]-'0'; if (q) m*=q;
        if (s<m) s=m;
        q=a[i  ]-'0'; if (q) m/=q;
        }
    
  2. также вы можете сделать таблицу для mul, div операций для скорости (но это не быстрее во всех случаях)

        int mul_5digits[9*9*9*9*9+1][10]={ 0*0,0*1,0*2, ... ,9*9*9*9*9/9 };
        int div_5digits[9*9*9*9*9+1][10]={ 0/0,0/1,0/2, ... ,9*9*9*9*9/9 };
        // so a=b*c; is rewritten by a=mul_5digits[b][c];
        // so a=b/c; is rewritten by a=div_5digits[b][c];
    
    • конечно, вместо значений 0 * 0 нужно добавить нейтральное value = 1 !!!
    • конечно, вместо значений i/0 нужно добавить нейтральное value = i !!!

      int i=0,s=0,t=1;
      for (i=0;i<4;i++)
          {
          t=mul_5digits[t][a[i  ]-'0'];
          }
      for (i=0;i<996;i++)
          {
          t=mul_5digits[t][a[i+4]-'0'];
          if (s<t) s=t;
          t=div_5digits[t][a[i  ]-'0'];
          }
      

Измерения времени выполнения на AMD 3.2GHz, 64 бит Win7, 32-битное приложение BDS2006 C++:

0.022ms classic approach
0.013ms single mul,div per step (produce false outut if there is none product > 0 present)
0.054ms tabled single mul,div per step (is slower for my setup)

PS.

Все улучшения кода должны быть измерены, поэтому вы видите, действительно ли вы ускоряете работу или нет.
Потому что быстрее для одного компилятора/платформы/компьютера может быть медленнее для другого.
Используйте разрешение не менее 0,1 мс.
Я предпочитаю использовать RDTSC или PerformanceCounter для этого.

0

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

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

0

За исключением ошибок, отмеченных в комментариях, много умножений не требуется. Если вы начинаете с произведения [0] * [1] * [2] * [3] * [4] для индекса 0, то каким будет произведение, начинающееся с [1]? Старый результат делится на [0] и умножается на [5]. Одно деление и одно умножение могут быть быстрее, чем 4 умножения

  • 0
    За исключением случаев, когда [0] было 0 ..., поскольку это имеет дело с однозначными числами, я действительно не думаю, что эта оптимизация будет иметь какой-либо видимый эффект.
  • 0
    Вы, вероятно, правы, что эффект будет невелик для «только» 1000 однозначных чисел, и я сам не уверен, будет ли он быстрее, а не медленнее. Но это "могло" быть;)

Ещё вопросы

Сообщество Overcoder
Наверх
Меню