All computations should be performed in the extended field:
Operation rules:
Addition
Multiplication
Let x = a + b \sqrt{c}. Then the required sum is a finite geometric progression:
It remains to perform the division a = x^{n + 1} - 1 by b = x - 1 in the field Z_p (\sqrt{c}):
Example
In the first example
Let's compute this example using the formula:
In the second example
Algorithm implementation
The function modpow computes the value a^k~mod~p.
long long modpow(long long a, long long k, long long p)
{
long long res = 1;
a %= p;
while (k)
{
if (k & 1) res = res * a % p;
a = a * a % p;
k >>= 1;
}
return res;
}Let's define a structure to store numbers of the form x + y \sqrt{c}.
struct Num
{
long long x, y; // x + y*sqrt(c)
};Let's implement addition in the field Z_p (\sqrt{c}). The function add returns the sum of two numbers and .
Num add(Num& a, Num& b)
{
Num res;
res.x = (a.x + b.x) % p;
res.y = (a.y + b.y) % p;
return res;
}Let's implement subtraction in the field Z_p (\sqrt{c}). The function sub returns the difference of two numbers and .
Num sub(Num& a, Num& b)
{
Num res;
res.x = (a.x - b.x + p) % p;
res.y = (a.y - b.y + p) % p;
return res;
}Let's implement multiplication in the field Z_p (\sqrt{c}). The function mult returns the product of two numbers and .
Num mult(Num& a, Num& b)
{
Num res;
res.x = (a.x * b.x + c * a.y % p * b.y) % p;
res.y = (a.x * b.y + a.y * b.x) % p;
return res;
}The function pow implements exponentiation of base^n, where is an element of the field Z_p (\sqrt{c}).
Num pow(Num base, long long n)
{
Num res = { 1, 0 }; // единица поля
while (n > 0)
{
if (n & 1)
res = mult(res, base);
base = mult(base, base);
n >>= 1;
}
return res;
}The function divide implements division in the field Z_p (\sqrt{c}). It returns the quotient of the numbers and . The division is performed by multiplying by the conjugate:
Num divide(Num& a, Num& b)
{Let conj = b_x - b_y \sqrt{c}.
Num conj = { b.x, (p - b.y) % p };Compute n = (a_x + a_y \sqrt{c})(b_x - b_y \sqrt{c}).
Num n = mult(a, conj);Compute denom = b_x^2 - b_y^2 c.
long long denom =
((b.x * b.x) % p - ((b.y * b.y) % p * c) % p + p) % p;Compute the multiplicative inverse and return n / denom = n \cdot denom^{-1}.
long long inv_denom = modpow(denom, p - 2, p); // обратный элемент
return Num((n.x * inv_denom) % p, (n.y * inv_denom) % p);
}The main part of the program. Read the input data.
scanf("%lld %lld %lld %lld %lld", &a, &b, &c, &n, &p);Initialize the number x = a + b \sqrt{c} and the multiplicative identity of the field one = 1 + 0 \sqrt{c}.
Num x = { a % p, b % p };
Num one = { 1, 0 };Compute num = x^{n+1} - 1, denom = x - 1.
Num num = pow(x, n + 1);
num = sub(num, one);
Num denom = sub(x, one);Compute and print the answer res = num / denom = \frac{x^{n+1} - 1}{x - 1}.
Num res = divide(num, denom);
printf("%lld %lld\n", res.x, res.y);