Я написал небольшой алгоритм, который вычисляет серию чисел, но в конечном итоге они становятся большими для хранения в unsigned long long
. Вот почему я решил принимать по модулю каждый раз, когда вычисляется следующий номер. Это моя функция:Небольшая ошибка при использовании modulo
#define MOD 1000000007
template <typename T>
T modpow(T base, T exp, T modulus) {
base %= modulus;
T result = 1;
while (exp > 0) {
if (exp & 1) result = (result * base) % modulus;
base = (base * base) % modulus;
exp >>= 1;
}
return result;
}
vector<unsigned long long> B(int n) {
vector<unsigned long long> points;
vector<unsigned long long> cum_points;
points.push_back(0);
points.push_back(0);
cum_points = points;
unsigned long long prev = 0;
if (n >= 2){
for (int i = 0; i <= n - 2; i++) {
prev += cum_points[i];
prev %= MOD;
points.push_back((modpow((unsigned long long)2, (unsigned long long)i, (unsigned long long) MOD)+prev)%MOD);
cum_points.push_back((cum_points[i+1]+points[i+2])%MOD);
}
}
return points;
}
Это возвращает вектор с серией цифр:
0, 0, 1, 2, 5, 12, 28, 64, 144, 320 , 704, 1536, 3328, ...
И так далее ...
Проблемы заключается в том, что, когда n > 50
по модулю немного от: (Первых значений являются те, рассчитанными без модуля в коде, а значения после знаков равенства результатов с по модулю в коде.)
50: 1759218604441600 % 1000000007 = 592127074; this is the right answer
51: 3588805953060860 % 1000000007 = 927939229; this should be: 927939225
ошибка становится немного больше, каждый раз, когда n
получает больше. Откуда это небольшое смещение?
Некоторые возможные проблемы:
modpow()
как-то не дает правильный ответ, когда число превышает определенную длину. Это не проблема- Существует некоторая ошибка с математикой, однако я считаю, что я использовал следующие уравнения правильный путь:
(a*b) mod c = ((a mod c)*(b mod c)) mod c
(a + b) mod c = ((a mod c)+(b mod c)) mod c
- Я мог бы также иметь неправильный тип переменной в моем коде, хотя я не знал бы где.
EDIT: я исключил некоторые из возможных проблем, и проблема, кажется, лежит в расчете prev
при i == 48
.
Максимальный размер unsigned long long в моей системе: '18446744073709551615', который должен быть достаточно большим для операций с модулем. ('unsigned int': 4294967295). 'Constexpr' не работает, поскольку он еще не поддерживается VS 2013. – kdnooij