Подтвердить что ты не робот

Модуль с отрицательными номерами в С++

Я пишу программу для следующего рекуррентного отношения:

An = 5An-1 - 2An-2  - An-3 + An-4

Выход должен быть модулем ответа 10 ^ 9 + 7.. Я написал метод грубой силы для этого следующего:

long long int t1=5, t2=9, t3=11, t4=13, sum;
while(i--)
{
    sum=((5*t4) - 2*t3 - t2 +t1)%MOD;
    t1=t2;
    t2=t3;
    t3=t4;
    t4=sum;
}
printf("%lld\n", sum);

где MOD= 10^9 +7 Кажется, что все кажется правдой, но я получаю отрицательный ответ за некоторые ценности... и из-за этой проблемы я не могу найти правильное решение... Plz поможет найти подходящее место для хранения Modulus

4b9b3361

Ответ 1

Дело в том, что оператор% не является "модульным оператором", а оператором "деления остатка" со следующим равенством

(a/b)*b + a%b == a    (for b!=0)

Итак, если в случае, если ваше целочисленное деление округляется к нулю (что, как мне кажется, предусмотрено с C99 и С++ 11), -5/4 будет -1, и мы имеем

(-5/4)*4 + -5%4 == -5
  -1  *4    -1  == -5

Чтобы получить положительный результат (для операции с модулем), вам нужно добавить делитель, если остаток был отрицательным или сделать что-то вроде этого:

long mod(long a, long b)
{ return (a%b+b)%b; }

Ответ 2

Используя % второй раз в @sellibitze и @liquidblueocean ответы, вероятно, будут не такими медленными, как %, как правило, в целом, потому что он сводится к одному вычитанию b или none. Собственно, позвольте мне просто проверить, что...

int main(int argc, char **argv) {
    int a = argc;    //Various tricks to prevent the
    int b = 7;       //compiler from optimising things out.
    int c[10];       //Using g++ 4.8.1
    for (int i = 0; i < 1000111000; ++i)
        c[a % b] = 3;
        //c[a < b ? a : a-b] = 3;
    return a;
}

Альтернативно комментируя строку с помощью % или другой строки, мы получаем:

  • С %: 14 секунд

  • С ?: 7 секунд

Итак, % не так оптимизирован, как я подозревал. Вероятно, потому, что эта оптимизация добавит служебные данные.

Следовательно, лучше не использовать % дважды, по соображениям производительности.

Вместо этого, как этот ответ предлагает и объясняет, сделайте следующее:

int mod(int k, int n) {
    return ((k %= n) < 0) ? k+n : k;
}

Требуется немного больше работать, если вы хотите, чтобы он правильно работал для отрицательного n тоже, но это почти никогда не нужно.

Ответ 3

Просто замените % на функцию, которая обрабатывает отрицательные значения:

long long int mod(long long int a, long long int b) {
    long long int ret = a % b;
    if (ret < 0)
        ret += b;
    return ret;
}

EDIT: изменил тип данных на long long int.

Ответ 4

Все ответы на данный момент, которые имеют одноразовое дополнение в их формуле, ошибочны, когда abs (a) > b. Используйте это или подобное:

int modulo (int a, int b) { return a >= 0 ? a % b : ( b - abs ( a%b ) ) % b; }

Ответ 5

Как говорили другие, % - это просто оператор остатка, а не mod. Тем не менее, операция mod/else распределяется правильно через такие повторяющиеся отношения, поэтому, если вы просто скорректируете свое окончательное решение как положительное, например,

if (sum < 0) { sum = sum + MOD; }

тогда вы должны получить правильный ответ. Преимущество этого заключается в том, что вы вводите один меньше вызовов функции и/или ветки на каждую итерацию цикла. (Что может или не может иметь значения в зависимости от того, насколько умный ваш компилятор).