Последовательность n чисел - вычислить все возможные k-подпоследовательности счастливых чисел

У меня проблема с одной задачей, поэтому, если бы вы могли мне немного помочь.

Числа бывают «счастливыми» или «несчастливыми». Число «счастливое», если каждая цифра 7 или каждая цифра равна 4. Таким образом, «счастливыми» числами являются, например, 4, 44, 7, 77. «Несчастливыми» являются остальные числа.
Вы получите последовательность n- элементов и число K. Ваша задача — вычислить количество всех возможных k-элементных подпоследовательностей, удовлетворяющих одному условию. Условие состоит в том, что в подпоследовательности не должно быть двух одинаковых «счастливых» чисел. Так, например, не должно быть 77 и 77... Выведите число всех возможных подпоследовательностей k-элементов по модулю 10^9+7 0 ‹ N,K ‹ 10^5

Few examples:
Input:

5 2
7 7 3 7 77
Output:

7

Input:

5 3
3 7 77 7 77
Output:

4

Input:

34 17
14 14 14 ... 14 14 14
Output:

333606206

У меня есть код, который работает, но он слишком медленный, когда я пытаюсь вычислить биномиальный коэффициент. Я использую карту. В строке я храню число в строковом формате. Во второй - int - часть карты представляет собой число, которое представляет, сколько раз использовалось это число (в первом параметре карты). Итак, теперь я сохранил все «несчастливые» числа вместе. Также все одинаковые «счастливые» числа совпадают. Когда я храню его таким образом, я просто вычисляю все умножения. Например:

Input 
5 2
3 7 7 77 7
Are stored like this:  map["other"] = 1 map["7"] = 3 map["77"] = 1 
Because k = 2 --> result is: 1*3 + 1*1 + 1*3 = 7.

Я думаю, что проблема заключается в вычислении биномиального коэффициента. Для третьего примера ему нужно вычислить (34 выбрать 17), и он вычисляет очень долго. for-large-nk">эта статья, а также эта, но я не не понимаю, как они решают эту проблему.

Мой код:

#include<iostream>
#include<string>
#include<map>
#include <algorithm>
#include <vector>

using namespace std;

int binomialCoeff(int n, int k)
{
    // Base Cases
    if (k == 0 || k == n)
        return 1;

    // Recur
    return  binomialCoeff(n - 1, k - 1) + binomialCoeff(n - 1, k);
}

int main()
{
    int n, k;
    cin >> n >> k;
    map<string, int> mapa;  // create map, string is a number, int represents number of used string-stored numbers ---> so if 7 was used two times, in the map it will be stored like this mapa["7"] == 2 and so on)
    for (int i = 0; i < n; i++)  // I will load number as string, if this number is "lucky" - digist are all 7 or all 4
    {                            // every "unlucky" numbers are together, as well as all same "lucky" numbers ---> so 77 and 77 will be stored in one element....
        string number;
        cin >> number;
        char digit = number[0];
        bool lucky = false;
        if (digit == '7' || digit == '4')
            lucky = true;
        for (int j = 1; j < number.length(); j++) {
            if (digit != '7' && digit != '4')
                break;
            if (number[j] != digit) {
                lucky = false;
                break;
            }
        }
        if (lucky)
            mapa[number]++;
        else
            mapa["other"]++;
    }
    vector<bool> v(mapa.size());
    bool lack = k > mapa.size(); //lack of elements in map --> it is when mapa.size() < k; i. e. number of elements in array can't make k-element subsequence.
    int rest = lack ? k - mapa.size() + 1 : 1;  // how many elements from "unlucky" numbers I must choose, so it makes base for binomial coefficient (n choose rest)
    if (lack)  //if lack is true, different size of vector
        fill(v.begin() + mapa.size(), v.end(), true);
    else
        fill(v.begin() + k, v.end(), true);
    int *array = new int[mapa.size()];   //easier to manipulate with array for me
    int sum = 0;  
    int product = 1;
    int index = 0; 
    for (map<string, int> ::iterator pos = mapa.begin(); pos != mapa.end(); ++pos)  // create array from map
    {
        if (lack && pos->first == "other") {    //if lack of elements in map, the number in elemets representing "unlucky" numbers will be binomial coefficient (mapa["other] choose rest)
            array[index++] = binomialCoeff(mapa["other"], rest);
            continue;
        }
        array[index++] = pos->second;
    }
    do {   // this will create every posible multiplication for k-elements subsequences
        product = 1;
        for (int i = 0; i < mapa.size(); ++i) {
            if (!v[i]) {
                product *= array[i];
            }
        }
        sum += product;
    } while (next_permutation(v.begin(), v.end()));
    if (mapa["other"] >= k && mapa.size() > 1) {   // if number of "unlucky" numbers is bigger than k, we need to compute all possible  k-elements subsequences just from "unlucky" number, so binomial coefficient (mapa["other] choose k)
        sum += binomialCoeff(mapa["other"], k);
    }
    cout << sum % 1000000007 << endl;
}

person Jozef Bugoš    schedule 16.11.2015    source источник
comment
Перво-наперво. Найдите другой метод вычисления биномиальных коэффициентов (погуглите). Вы используете едва ли не худший из возможных методов. Имейте в виду, что необходимые вам биномиальные коэффициенты будут переполнять int в ваших примерах.   -  person n. 1.8e9-where's-my-share m.    schedule 17.11.2015
comment
Да, знаю. Я нашел эту статью, а также this , но я не понимаю, как это сделать. Полагаю, это должно быть очень быстро, потому что в моем случае оба 0 ‹ N,K ‹= 10 ^ 5   -  person Jozef Bugoš    schedule 17.11.2015
comment
Это выглядит как идеальное совпадение для решения в однострочнике haskell:/   -  person Netwave    schedule 17.11.2015
comment
Каков диапазон чисел в последовательности?   -  person Pham Trung    schedule 17.11.2015
comment
Небольшой совет: количество различных счастливых номеров будет небольшим, всего менее 1000 чисел (максимум 9 цифр, поэтому 2 ^ 9 + 2 ^ 8 + ... + 2 ~ 1000), которые вы можете использовать динамическое программирование для расчета часть счастливого числа. Для части несчастливых чисел, поскольку нам нужно рассчитать только 1000 комбинаций, мы можем использовать < href="https://en.wikipedia.org/wiki/Fermat%27s_little_theorem" rel="nofollow noreferrer">маленькая теорема Ферма.   -  person Pham Trung    schedule 17.11.2015
comment
Ты прав. На самом деле существует всего 18 типов счастливых чисел, не так ли? 4,44,444....444444444 и то же самое для 7. Кроме того, я не понимаю, как использовать маленькую теорему Ферма для вычисления комбинаций.   -  person Jozef Bugoš    schedule 17.11.2015
comment
Для комбинации C(a, b) = a! / (b! (a - b)!), а нам нужно вычислить C(a, b) mod 10^9 + 7, мы не можем напрямую вычислить мод C(a, b), однако обратите внимание, что 10^9 + 7 — простое число, поэтому мы можем использовать теорему, см. один объяснение здесь   -  person Pham Trung    schedule 18.11.2015
comment
Итак, я нашел эту статью, и теперь у меня есть код, который отлично работает :)   -  person Jozef Bugoš    schedule 18.11.2015
comment
Отлично :), в следующий раз, пожалуйста, используйте @ + Name, чтобы уведомить человека, с которым вы разговариваете, например, @PhamTrung, чтобы уведомить меня :D   -  person Pham Trung    schedule 19.11.2015
comment
@PhamTrung спасибо, я это запомню :)   -  person Jozef Bugoš    schedule 19.11.2015