задачки с хедхантера
От: Кодт Россия  
Дата: 12.10.16 14:07
Оценка: 5 (1)
На хабре статья с, как выяснилось, неудачными решениями задачек
https://habrahabr.ru/post/311908/

Предлагаю размять голову самостоятельно.

Итак

Задача 1
Дано равенство, в котором цифры заменены на буквы: rqr + rqq = sqr. Найдите сколько у него решений, если различным буквам соответствуют различные цифры (ведущих нулей в числе не бывает).

Задача 2
Наименьшее число m, такое, что m! делится без остатка на 10 — это m=5 (5! = 120). Аналогично, наименьшее число m, такое, что m! делится без остатка на 25 — это m=10. В общем случае, значение функции s(n) равно наименьшему числу m, такому что m! без остатка делится на n.
Определим функцию S(M, N) = ∑s(n) для всех n ∈ [M, N]. К примеру, S(6, 10) = 3 + 7 + 4 + 6 + 5 = 25. Найдите S(2300000, 2400000).

Задача 3
Рассмотрим все возможные числа ab для 1<a<6 и 1<b<6:
22=4, 23=8, 24=16, 25=32 32=9, 33=27, 34=81, 35=243 42=16, 43=64, 44=256, 45=1024, 52=25, 53=125, 54=625, 55=3125. Если убрать повторения, то получим 15 различных чисел. Сколько различных чисел ab для 2<a<135 и 2<b<136?
Перекуём баги на фичи!
Re: задачки с хедхантера
От: Sharov Россия  
Дата: 12.10.16 15:57
Оценка:
Здравствуйте, Кодт, Вы писали:

К>На хабре статья с, как выяснилось, неудачными решениями задачек

К>https://habrahabr.ru/post/311908/

К>Предлагаю размять голову самостоятельно.


К>Итак


К>Задача 1

К>Дано равенство, в котором цифры заменены на буквы: rqr + rqq = sqr. Найдите сколько у него решений, если различным буквам соответствуют различные цифры (ведущих нулей в числе не бывает).

С разбегу решилось сл. образом:
q = 0, s = 2r

Возможно обшибся. Остальные посмотрю потом.
Кодом людям нужно помогать!
Re[2]: задачки с хедхантера
От: Muxa  
Дата: 12.10.16 16:07
Оценка: +1
К>>Задача 1
К>>Дано равенство, в котором цифры заменены на буквы: rqr + rqq = sqr. Найдите сколько у него решений, если различным буквам соответствуют различные цифры (ведущих нулей в числе не бывает).

S>С разбегу решилось сл. образом:

S>q = 0, s = 2r
S>Возможно обшибся. Остальные посмотрю потом.

Уточню:
rqr + rqq = sqr
=> q = 0
подставляем q = 0: r0r + r00 = s0r
=> s = 2*r
=> r = 1..4
4 решения
101 + 100 = 201
202 + 200 = 402
303 + 300 = 603
404 + 400 = 804
Re: задачки с хедхантера
От: Lexey Россия  
Дата: 13.10.16 10:35
Оценка: :)
Здравствуйте, Кодт, Вы писали:

К>На хабре статья с, как выяснилось, неудачными решениями задачек

К>https://habrahabr.ru/post/311908/

OMG. Они там факториалы решили в лоб считать.
"Будь достоин победы" (c) 8th Wizard's rule.
Re[2]: задачки с хедхантера
От: Кодт Россия  
Дата: 13.10.16 12:12
Оценка: :)
Здравствуйте, Lexey, Вы писали:

L>OMG. Они там факториалы решили в лоб считать.


Не стреляйте в пианистку, девочка играет, как умеет Ей в комментах уже попрекнули и факториалами, и степенями.
Перекуём баги на фичи!
Re: задачки с хедхантера
От: Кодт Россия  
Дата: 13.10.16 14:57
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Задача 2

К>Наименьшее число m, такое, что m! делится без остатка на 10 — это m=5 (5! = 120). Аналогично, наименьшее число m, такое, что m! делится без остатка на 25 — это m=10. В общем случае, значение функции s(n) равно наименьшему числу m, такому что m! без остатка делится на n.
К>Определим функцию S(M, N) = ∑s(n) для всех n ∈ [M, N]. К примеру, S(6, 10) = 3 + 7 + 4 + 6 + 5 = 25. Найдите S(2300000, 2400000).

У меня на питоне без особых оптимизаций это заняло 9 секунд. Ответ 324780928, надеюсь, что правильный.
Перекуём баги на фичи!
Re[2]: задачки с хедхантера
От: Lexey Россия  
Дата: 13.10.16 15:55
Оценка: 15 (1)
Здравствуйте, Кодт, Вы писали:

К>У меня на питоне без особых оптимизаций это заняло 9 секунд. Ответ 324780928, надеюсь, что правильный.


Ты малость схалявил. Твой ответ верный, но для S(230000, 240000). А нужно было S(2300000, 2400000).

У меня получилось 27566064194.
  Код
#include <cmath>
#include <vector>
#include <iostream>
#include <tuple>
#include <chrono>

using namespace std;

vector<int> primes({ 2, 3, 5, 7, 11, 13 });

void genPrimes(int max) {
    for (int n = 15; n <= max; n += 2) {
        auto it = primes.begin() + 1;
        for (;;) {
            if (it == primes.end()) {
                primes.push_back(n);
                break;
            }
            if (n % *it == 0) break;
            ++it;
        }
    }
}

int s(int n);

int main() {
    auto t1 = chrono::high_resolution_clock::now();
    constexpr int m = 2300000;
    constexpr int n = 2400000;
    genPrimes(static_cast<int>(sqrt(n)));
    int64_t result = 0;
    for (auto i = m; i <= n; ++i)
    {
        result += s(i);
    }
    cout << result << endl;
    auto t2 = chrono::high_resolution_clock::now();
    cout << "time: " << chrono::duration_cast<chrono::milliseconds>(t2 - t1).count() << "ms" << endl;
}

vector<tuple<int, int>> factorize(int n);
int factorial_power(int m, int p);

int s(int n)
{
    auto factors = factorize(n);
    int lb = 1;
    for (auto v: factors)
    {
        int p;
        int count;
        tie(p, count) = v;
        int lb_value = factorial_power(lb, p);
        if (lb_value >= count) continue;
        int ub = p * count;
        if (count < p)
        {
            lb = ub;
            continue;
        }
        while (lb < ub)
        {
            int median = lb + (ub - lb) / 2;
            int m_value = factorial_power(median, p);
            if (m_value < count)
            {
                lb = median + 1;
            }
            else
            {
                ub = median;
            }
        }
    }
    return lb;
}

int factorial_power(int m, int p)
{
    int result = 0;
    while (m >= p)
    {
        result += m / p;
        m /= p;
    }
    return result;
}

vector<tuple<int, int>> factorize(int n) {
    vector<tuple<int, int>> result;
    for (auto p : primes) {
        int count = 0;
        while (n % p == 0)
        {
            ++count;
            n /= p;
        }
        if (count > 0)
        {
            result.push_back(make_tuple(p, count));
        }
        if (p > n) break;
    }
    if (n > 1)
    {
        result.push_back(make_tuple(n, 1));
    }
    return result;
}

В релизе 137 мс. И можно пооптимизировать еще.
"Будь достоин победы" (c) 8th Wizard's rule.
Отредактировано 13.10.2016 16:12 Lexey . Предыдущая версия . Еще …
Отредактировано 13.10.2016 16:10 Lexey . Предыдущая версия .
Отредактировано 13.10.2016 15:58 Lexey . Предыдущая версия .
Отредактировано 13.10.2016 15:57 Lexey . Предыдущая версия .
Re[3]: задачки с хедхантера
От: Кодт Россия  
Дата: 13.10.16 17:24
Оценка:
Здравствуйте, Lexey, Вы писали:

L>Ты малость схалявил. Твой ответ верный, но для S(230000, 240000). А нужно было S(2300000, 2400000).

<>

Прикольный способ!
Попробую-ка щас на питоне — интересно, насколько он быстрее будет...

На самом деле, бисекция тут лишняя. Щас формулу рожу...
Перекуём баги на фичи!
Re[3]: задачки с хедхантера
От: cures Россия cures.narod.ru
Дата: 13.10.16 17:31
Оценка: 5 (1)
Здравствуйте, Lexey, Вы писали:

L>В релизе 137 мс. И можно пооптимизировать еще.


Нужно! Двоичный поиск — дело хорошее, но он (квадратно) логарифмичен, один логарифм можно снять, если взять нижнюю границу для конкретного p равной count * (p — 1) + 1 (из суммы геометрической прогрессии), округлённому вверх до делящегося на p, а потом идти вверх шажками по p, не перевычисляя заново факториальную степень, а подсчитывая количество p в очередном множителе (в среднем это будет не более одной проверки), а шажков таких уже будет логарифмическое число. И порядком простых множителей можно поиграться, современные автоматические форы — это клёво, но если идти обратно, и есть достаточно большой простой множитель, то возможно его хватит для оставшихся маленьких (в Вашем примере — будем сразу улетать на continue), в целом это может оказаться выгодным. Ну и факторизация каждого числа — это жесть, для таких маленьких чисел тупо составляется решето на 2.4М интов, в котором каждому числу сопоставляется один из его простых множителей, тут наверное будет самый толстый выигрыш. Ну или хотя бы стандартно до корня перебирать возможные простые делители, а не до самого числа.
В общем печально всё с этим хантером, у них даже близко ничего нет к разумному решению.
Re[4]: задачки с хедхантера
От: Lexey Россия  
Дата: 13.10.16 17:56
Оценка:
Здравствуйте, cures, Вы писали:

L>>В релизе 137 мс. И можно пооптимизировать еще.


C>Нужно!


Не факт. И так очень шустро работает.

C>Двоичный поиск — дело хорошее, но он (квадратно) логарифмичен, один логарифм можно снять, если взять нижнюю границу для конкретного p равной count * (p — 1) + 1 (из суммы геометрической прогрессии), округлённому вверх до делящегося на p, а потом идти вверх шажками по p, не перевычисляя заново факториальную степень, а подсчитывая количество p в очередном множителе (в среднем это будет не более одной проверки), а шажков таких уже будет логарифмическое число.


Тут согласен.

C>И порядком простых множителей можно поиграться, современные автоматические форы — это клёво, но если идти обратно, и есть достаточно большой простой множитель, то возможно его хватит для оставшихся маленьких (в Вашем примере — будем сразу улетать на continue), в целом это может оказаться выгодным.


Об этом думал, но не стал заморачиваться.

C>Ну и факторизация каждого числа — это жесть, для таких маленьких чисел тупо составляется решето на 2.4М интов, в котором каждому числу сопоставляется один из его простых множителей, тут наверное будет самый толстый выигрыш.


Идея хорошая. Но, не принципиально, ибо факторизация все равно будет линейной (только константа уменьшается), а мороки с реализацией больше.

C>Ну или хотя бы стандартно до корня перебирать возможные простые делители, а не до самого числа.


Перебираются простые до корня из N. Корень из конкретного числа в данной задаче не сильно меньше будет.

C>В общем печально всё с этим хантером, у них даже близко ничего нет к разумному решению.


Это да.
"Будь достоин победы" (c) 8th Wizard's rule.
Re[5]: задачки с хедхантера
От: cures Россия cures.narod.ru
Дата: 13.10.16 18:06
Оценка:
Здравствуйте, Lexey, Вы писали:

L>Не факт. И так очень шустро работает.


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

C>>Ну и факторизация каждого числа — это жесть, для таких маленьких чисел тупо составляется решето на 2.4М интов, в котором каждому числу сопоставляется один из его простых множителей, тут наверное будет самый толстый выигрыш.


L>Идея хорошая. Но, не принципиально, ибо факторизация все равно будет линейной (только константа уменьшается), а мороки с реализацией больше.


Факторизация будет (практически) линейной по максимальному числу, а при независимой факторизации она требует примерно количество чисел в диапазоне, помноженной на корень из большего числа, то есть в худшем случае — большее число в степени 1.5.


L>Перебираются простые до корня из N. Корень из конкретного числа в данной задаче не сильно меньше будет.


Нет, перебираются до самого N. Вот если бы Вы заменили if (p > n) break; на if (p > n / p) break; то перебирались бы до корня.

Update: понял, перебираются до корня из максимального числа, но достаточно часто будут иметься маленькие множители, что сократит перебор. Можете попробовать.
Отредактировано 13.10.2016 18:08 cures . Предыдущая версия .
Re[4]: задачки с хедхантера
От: Кодт Россия  
Дата: 13.10.16 18:13
Оценка:
Здравствуйте, cures, Вы писали:

C>Здравствуйте, Lexey, Вы писали:


L>>В релизе 137 мс. И можно пооптимизировать еще.


C>Нужно! Двоичный поиск — дело хорошее


Нуу... да, пожалуй.
Альтернатива этому — написать прямую формулу логарифма, который находил бы для очередной пары (p**count) точное значение m : m! >= p**count,
там будет что-то типа p * (какой-то ряд из int(count/p**k))

Кстати, если сплавить разложение и нахождение границы, то можно избавиться от вектора.
Просто рожаем очередную степень очередного простого числа, и тут же находим m для неё.
А в забеге находим максимум.
Перекуём баги на фичи!
Re[5]: задачки с хедхантера
От: cures Россия cures.narod.ru
Дата: 13.10.16 18:23
Оценка: 20 (2)
Здравствуйте, Кодт, Вы писали:

К>там будет что-то типа p * (какой-то ряд из int(count/p**k))


Это равно count * (p — 1), плюс совсем чуть-чуть, что за логарифмическое число шагов подбирается.

К>Кстати, если сплавить разложение и нахождение границы, то можно избавиться от вектора.


А смысл? Вектор простых делителей маленький, компилятор скорее всего соптимизирует его переприсвоения. Но сейчас нет смысла даже убирать логарифм, всё время (35ms) уходит на факторизацию, попробуйте вставить return factors.size(); в самое начала функции s после вычисления факторов. Сначала надо делать решето.

Update1: Вот накодил с решетом и ступеньками, поднял оба лимита в 10 раз, предлагаю на них и меряться, на старых слишком волатильно, а больше идеван вряд ли памяти даст.

Update2: Сделал решето двухбайтовым, перестал лишний раз считать factorial_power; чуть уменьшилось время, до 0.31 секунды. Замерил число прыжков по ступенькам (неугадывание по формуле), 17355 на миллион, это даже не логарифм, а очень хорошая константа.
Отредактировано 13.10.2016 21:02 cures . Предыдущая версия . Еще …
Отредактировано 13.10.2016 19:42 cures . Предыдущая версия .
Re: задачки с хедхантера
От: Lexey Россия  
Дата: 13.10.16 21:42
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Задача 3

К>Рассмотрим все возможные числа ab для 1<a<6 и 1<b<6:
К>22=4, 23=8, 24=16, 25=32 32=9, 33=27, 34=81, 35=243 42=16, 43=64, 44=256, 45=1024, 52=25, 53=125, 54=625, 55=3125. Если убрать повторения, то получим 15 различных чисел. Сколько различных чисел ab для 2<a<135 и 2<b<136?

Тут получилось 16640. Решение мне не очень нравится из-за того, что все-таки пришлось степени в set пихать в двойном цикле. Но ничего лучшего пока не придумалось.
  Код
#include <cmath>
#include <vector>
#include <iostream>
#include <tuple>
#include <chrono>
#include <unordered_map>
#include <unordered_set>
#include <list>

using namespace std;

vector<int> primes({ 2, 3, 5, 7, 11 });

int solve(int minA, int maxA, int minB, int maxB);

int main() {
    auto t1 = chrono::high_resolution_clock::now();
    cout << solve(3, 134, 3, 135) << endl;
    auto t2 = chrono::high_resolution_clock::now();
    cout << "time: " << chrono::duration_cast<chrono::milliseconds>(t2 - t1).count() << "ms" << endl;
}

using factors = vector<tuple<int, int>>;
factors factorize(int n);
int h(factors const& v);
int gcd(int a, int b);

int solve(int minA, int maxA, int minB, int maxB)
{
    unordered_map<int, list<factors>> m;
    for (int a = minA; a <= maxA; ++a)
    {
        auto f = factorize(a);
        auto t = h(f);
        auto it = m.find(t);
        if (it == m.end())
        {
            list<factors> v;
            v.emplace_back(move(f));
            m.emplace(t, move(v));
        }
        else
        {
            it->second.emplace_back(move(f));
        }
    }
    int result = 0;
    for (auto t : m)
    {
        auto& l = t.second;
        while (!l.empty())
        {
            auto f1 = move(l.front());
            auto it = l.erase(l.begin());
            auto c1 = get<1>(f1[0]);
            list<factors> similar;
            while (it != l.end())
            {
                auto& f2 = *it;
                auto c2 = get<1>(f2[0]);
                auto g = gcd(c1, c2);
                auto m1 = c2 / g;
                auto m2 = c1 / g;
                bool compatible = true;
                for (size_t i = 1; i < f1.size(); ++i)
                {
                    if (get<1>(f1[i]) * m1 != get<1>(f2[i]) * m2)
                    {
                        compatible = false;
                        break;
                    }
                }
                if (!compatible)
                {
                    ++it;
                    continue;
                }
                similar.emplace_back(move(f2));
                it = l.erase(it);
            }
            if (similar.empty())
            {
                result += maxB - minB + 1;
                continue;
            }
            unordered_set<int> u;
            similar.emplace_front(move(f1));
            for (auto& t : similar)
            {
                auto m = get<1>(t[0]);
                for (int p = minB; p <= maxB; ++p)
                {
                    u.insert(m * p);
                }
            }
            result += u.size();
        }
    }
    return result;
}

int h(factors const& v)
{
    int h = 1;
    for (auto t : v)
    {
        h *= get<0>(t);
    }
    return h;
}

int gcd(int a, int b)
{
    for (;;)
    {
        int r = a % b;
        if (r == 0) return b;
        a = b;
        b = r;
    }
}

factors factorize(int n) {
    vector<tuple<int, int>> result;
    for (auto p : primes) {
        int count = 0;
        while (n % p == 0)
        {
            ++count;
            n /= p;
        }
        if (count > 0)
        {
            result.push_back(make_tuple(p, count));
        }
        if (p > n) break;
    }
    if (n > 1)
    {
        result.push_back(make_tuple(n, 1));
    }
    return result;
}
"Будь достоин победы" (c) 8th Wizard's rule.
Re[2]: задачки с хедхантера
От: cures Россия cures.narod.ru
Дата: 14.10.16 01:54
Оценка:
Здравствуйте, Lexey, Вы писали:

L>Тут получилось 16640. Решение мне не очень нравится из-за того, что все-таки пришлось степени в set пихать в двойном цикле. Но ничего лучшего пока не придумалось.


Выглядит немного жутковато. А почему бы не завести мапу с инта на сет интов, после разложения каждого основания a найдём его базовое основание A (разделив все показатели степеней простых факторов на их нод), и добавим в множество для A все показатели, которые вылезают из a, от g*bmin до g*bmax. После чего просто сложим мощности всех сетов. Возможно сеты даже излишни, хватит сегментов, но с сетами более общее решение.
Да, для a большего чем корень из amax, такого что A(a)=a, можно сет не заводить, оно как базовое больше никогда не всплывёт, можно сразу добавлять (bmax-bmin+1) к ответу. Итого базовых оснований в мапе будет 7 штук: [2,3,5,6,7,10,11]. Ещё до кучи можно мапу вообще не заводить, перебирать возможные базовые основания от 1 до sqrt(amax), помечать получающиеся из них степени и на ходу апдейтить соответствующий диапазон, так обходимся совсем без факторизации, но нужен битовый массивы размера (amax-amin+1) и sqrt(amax), и время работы будет пропорционально сумме их размеров, что вроде бы не хуже предлагаемого. Можно попробовать для solve(3,3000000000,4,4000000000).
Re: задачки с хедхантера
От: AlexeySmorkalov Россия https://ru.linkedin.com/pub/alexey-smorkalov/4/283/8b8
Дата: 14.10.16 06:43
Оценка: +2
К>Задача 1
К>Дано равенство, в котором цифры заменены на буквы: rqr + rqq = sqr. Найдите сколько у него решений, если различным буквам соответствуют различные цифры (ведущих нулей в числе не бывает).

Смущает, что никто не спросил уточнения про систему счисления.
Re[2]: задачки с хедхантера
От: Sharov Россия  
Дата: 14.10.16 10:38
Оценка:
Здравствуйте, AlexeySmorkalov, Вы писали:


К>>Задача 1

К>>Дано равенство, в котором цифры заменены на буквы: rqr + rqq = sqr. Найдите сколько у него решений, если различным буквам соответствуют различные цифры (ведущих нулей в числе не бывает).

AS>Смущает, что никто не спросил уточнения про систему счисления.


Справедливо, но лично я в этой задаче пошел кратчайшем путем. К тому же если не оговорено другого, то можно использовать "умолчание", т.е. десятичную сист. счисления.
Кодом людям нужно помогать!
Re[3]: задачки с хедхантера
От: Lexey Россия  
Дата: 14.10.16 10:45
Оценка:
Здравствуйте, cures, Вы писали:

C>Выглядит немного жутковато.


Да, есть такое.

C> А почему бы не завести мапу с инта на сет интов, после разложения каждого основания a найдём его базовое основание A (разделив все показатели степеней простых факторов на их нод), и добавим в множество для A все показатели, которые вылезают из a, от g*bmin до g*bmax. После чего просто сложим мощности всех сетов. Возможно сеты даже излишни, хватит сегментов, но с сетами более общее решение.


По факту, так и нужно было делать, но я сначала пытался просто дубликаты посчитать и их выкинуть из общего числа, но обломался. В итоге просто минимально переделал, чтобы работало. Целиком все перекраивать было просто лень, да и спать хотелось уже.

C>Да, для a большего чем корень из amax, такого что A(a)=a, можно сет не заводить, оно как базовое больше никогда не всплывёт, можно сразу добавлять (bmax-bmin+1) к ответу. Итого базовых оснований в мапе будет 7 штук: [2,3,5,6,7,10,11].


Согласен.

C>Ещё до кучи можно мапу вообще не заводить, перебирать возможные базовые основания от 1 до sqrt(amax), помечать получающиеся из них степени и на ходу апдейтить соответствующий диапазон, так обходимся совсем без факторизации, но нужен битовый массивы размера (amax-amin+1) и sqrt(amax), и время работы будет пропорционально сумме их размеров, что вроде бы не хуже предлагаемого. Можно попробовать для solve(3,3000000000,4,4000000000).


Вот эту идею не понял.
"Будь достоин победы" (c) 8th Wizard's rule.
Re: задачки с хедхантера
От: LaptevVV Россия  
Дата: 14.10.16 11:47
Оценка:
К>Задача 1
К>Дано равенство, в котором цифры заменены на буквы: rqr + rqq = sqr. Найдите сколько у него решений, если различным буквам соответствуют различные цифры (ведущих нулей в числе не бывает).
Один цикл от 1 до 4.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[4]: задачки с хедхантера
От: cures Россия cures.narod.ru
Дата: 14.10.16 14:11
Оценка:
Здравствуйте, Lexey, Вы писали:

C>>Ещё до кучи можно мапу вообще не заводить, перебирать возможные базовые основания от 1 до sqrt(amax), помечать получающиеся из них степени и на ходу апдейтить соответствующий диапазон, так обходимся совсем без факторизации, но нужен битовый массивы размера (amax-amin+1) и sqrt(amax), и время работы будет пропорционально сумме их размеров, что вроде бы не хуже предлагаемого. Можно попробовать для solve(3,3000000000,4,4000000000).


L>Вот эту идею не понял.


Перебираем базовые основания (не являющиеся степенями меньших чисел) до sqrt(amax). Например, 2 входит в отрезок [amin..amax] в степенях [2..7]. Соответствено, из списка базовых оснований вычёркиваем 4 и 8 (16 уже больше sqrt(134), а 2 ещё меньше 3), после чего для каждой из степеней двойки от второй до седьмой находим, сколько итоговых чисел она добавляет в результат. Например, 4 добавляет (bmax-bmin+1)=133 новых числа, 8 уже добавляет меньше, надо из её степеней вычесть те, которые мы уже добавили в четвёрке, 16 добавит ещё меньше, и так далее до 128. Количество добавляемых чисел придётся наверное считать по формуле включения-исключения (пересечение двух арифметических последовательностей вроде бы тоже арифметическая последовательность), поэтому к временнОй сложности добавится amax. Но таких базовых оснований, для которых будет много различных степеней, будет мало. Отдельно считаем количество чисел из отрезка [amin..amax], которые получались из наших степеней (уже сосчитаны); после пробега по базовым основаниям добавляем к итоговому результату количество непосчитанных оснований, умноженное на (bmax-bmin+1). Память нужна чтобы метить небазовые основания, битовый массив размера sqrt(amax), ну и стек размера log(amax) для рекурсивного вычисления по формуле включения-исключения.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.