Нет вывода для длинных длинных переменных типа int - PullRequest
0 голосов
/ 07 июня 2019

Вот фрагмент кода:

unsigned int m,n,a;
long long int c,p=0,q=0;
scanf("%u%u%u",&m,&n,&a);
while(m>0){
    m-=a;
    p++;
}
while(n>0){
    n-=a;
    q++;
}
c=p*q;
printf("%lld",c);

Приведенный выше код не работает для любого ввода.То есть кажется, что он разбился, хотя я не мог понять, где я ошибаюсь.Я думаю, что часть с % lld в printf имеет проблемы.Но я не знаю, как это исправить.Я использую блоки кода.

Некоторые ожидаемые выходы для соответствующих входов следующие:

Вход: 6 6 4

Выход: 4

Вход: 1000000000 1000000000 1

Выход: 1000000000000000000 (10 ^ 18).

APPEND:

Итак, я даю ссылку на основную проблему ниже.Логика моего кода казалась мне правильной.

https://codeforces.com/contest/1/problem/A

Ответы [ 3 ]

3 голосов
/ 07 июня 2019

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

Если вы посмотрите на вход 6 6 4 (т. Е. M = 6 и a = 4), вы увидите, что m сначала изменится, как m = 6 - 4, что приводит к m, равному 2. Так что в следующемцикл m изменится как m = 2 - 4, который должен быть равен -2, но, поскольку m не подписан, он будет преобразован в очень высокое положительное число (т. е. UINT_MAX-1), и цикл продолжится.Это не то, что вы хотите.

Чтобы исправить это, я предлагаю вам сбросить циклы while и просто сделать:

unsigned int m,n,a;
long long unsigned int c,p=0,q=0;
scanf("%u%u%u",&m,&n,&a);
p = (m + a - 1)/a;          // Replaces first while
q = (n + a - 1)/a;          // Replaces second while
c=p*q;
printf("%lld",c);

Одна проблема с этим решением состоит в том, что сумма (m + a - 1) может переполниться (т. е. быть больше, чем UINT_MAX) и, следовательно, дать неправильные результаты.Вы можете исправить это, добавив проверку переполнения перед суммой.

Еще один способ защиты от переполнения может быть:

  p = 1;                // Start with p=1 to handle m <= a
  if (m > a)
  {
    m -= a;             // Compensate for the p = 1 and at the same time
                        // ensure that overflow won't happen in the next line
    p += (m + a - 1)/a;
  }

Этот код может быть уменьшен до:

  p = 1;
  if (m > a)
  {
    p += (m - 1)/a;
  }
1 голос
/ 07 июня 2019
while(m>0){
    m-=a;
    p++;
}

будет работать до тех пор, пока m не станет равно 0, поскольку оно не может быть отрицательным, поскольку оно не подписано. Таким образом, если m равно 4, а a равно 6, то m снизится и получит максимальное значение, которое m может содержать минус 2. Вам следует изменить входные переменные на знаковые.

4386427 показывает, как вы можете использовать математику для полного удаления циклов, но для более общего случая вы можете сделать так:

while(m > a) {
    m-=a;
    p++;
}
// The above loop will run one iteration less
m-=a;
p++;

Конечно, вы должны сделать то же самое для второго цикла.

Другое дело, проверьте возвращаемое значение scanf:

if(scanf("%u%u%u",&m,&n,&a) != 3) {
    /* Handle error */
}
0 голосов
/ 07 июня 2019

Использование типа unsigned не всегда лучший выбор для представления положительных значений, особенно когда его модульное поведение не требуется (и, возможно, забыто, что приводит к «неожиданным» ошибкам).Вариант использования OP требует целочисленного типа, способного хранить значение максимум 10 9 , которое находится внутри диапазона 32-разрядного целого числа со знаком (безусловно, long int).

Как показывает ответ 4386427 , циклов while в коде OP можно (и нужно) избегать в любом случае, если только не требуется какое-либо решение "грубой силы" (что маловероятно, учитываяпроисхождение вопроса).

Я бы использовал функцию, хотя:

#include <stdio.h>

// Given 1 <= x, a <= 10^9
long long int min_n_of_tiles_to_pave_an_edge(long int x, long int a)
{
    if ( x > a ) {
        // Note that the calculation is performed with 'long' values and only after
        // the result is casted to 'long long', when it is returned
        return 1L + (x - 1L) / a;
    }
    else {
        return 1LL;
    }
}

int main(void)
{
    // Given a maximum value of  10^9, a 32-bit int would be enough.
    // A 'long int' (or 'long') is guaranteed to be capable of containing at
    // least the [−2,147,483,647, +2,147,483,647] range.
    long int m, n, a;

    while ( scanf("%ld%ld%ld", &m, &n, &a) == 3 )
    {
        // The product of two long ints may be too big to fit inside a long.
        // To be sure, performe the multiplication using a 'long long' type.
        // Note that the factors are stored in the bigger type, not only the
        // result.
        long long int c = min_n_of_tiles_to_pave_an_edge(m, a)
                        * min_n_of_tiles_to_pave_an_edge(n, a);

        printf("%lld\n",c);
    }
}
...