10673. Игра с округлением вниз и вверх
Теорема. Для двух целых чисел x и k всегда существуют
такие целые p и q, что
x = p + q
По заданным x и k
необходимо найти хотя бы одну такую пару p и q.
Вход.
Первая строка содержит количество тестов t (1 £ t £ 1000). Каждая следующая строка содержит два положительных
целых числа x и k (x, k < 108).
Выход. Для каждого теста вывести в
отдельной строке два числа: p и q. Если таких пар существует
несколько, то вывести одну из них. Значения p и q помещаются в 64-битовый целый тип.
3
5 2
40 2
4 6
Пример выхода
-5 5
0 2
0 4
расширенный алгоритм Евклида
Если x нацело делится на k,
то = = x / k.
Выбрав p = 0, q = k, получим: 0 * (x / k) + k
* (x / k) = x. Пусть x не делится на k. Если
n = , то m = = n + 1.
Поскольку НОД(n , m) = НОД(n , n + 1) = 1, то
исходя из расширенного алгоритма Евклида, существуют такие целые t и u,
что 1 = tn + um. Помножив равенство на x, получим x
= xtn + xum, откуда p = xt, q = xu.
Для первого теста имеет место
соотношение: 5 = (-5) * + 5 * = (-5) * 2 + 5 * 3.
При вычислении используем
64-битовый целый тип long long. Для простоты использования переопределим тип:
typedef long
long i64;
Расширенный алгоритм Евклида
имеет вид:
void gcdext(i64 a,i64 b, i64 *d, i64 *x,
i64 *y)
{
i64 s;
if (b == 0)
{
*d = a; *x = 1; *y = 0;
return;
}
gcdext(b,a % b,d,x,y);
s = *y;
*y = *x - (a / b) * (*y);
*x = s;
}
Читаем количество тестов. Для
каждого теста вводим значения x и k.
scanf("%d",&tests);
while(tests--)
{
scanf("%lld %lld",&x,&k);
Если x делится на k, то устанавливаем p = 0, q = k.
if (x % k
== 0) { p = 0; q = k;}
else
{
Иначе вычисляем n = и m = , запуская расширенный алгоритм Евклида. Он находит такие t
и u, что 1 = tn + um. Далее находим p = xt, q
= xu и выводим результат.
n = (int)floor(1.0
* x / k); m = (int)ceil(1.0 * x / k);
gcdext(n,m,&g,&t,&u);
p = t * x; q = u * x;
}
printf("%lld
%lld\n",p,q);
}