Skip to content

Commit f22da7b

Browse files
Added Tutorial for LOJ-1070 (en) (#436)
* Added LOJ-1070 * Added Title of the problem * Updated information * Added Code * nothing new * updated * Added Tutorial for LOJ-1070 (en) * Update en.md * Update en.md
1 parent 1f7cd15 commit f22da7b

File tree

1 file changed

+170
-0
lines changed

1 file changed

+170
-0
lines changed

1070/en.md

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
# LOJ 1070 - Algebraic Problem
2+
3+
## Summary
4+
Given three non-negative integers, a+b = **p**, ab = **q** and **n** we have to find the value of $a^n$ + $b^n$. a and b not necessarily have to be integers. There will be no such input so that we have to find the value of $0^0$
5+
6+
## Prerequisite
7+
Matrix Exponentiation: https://www.youtube.com/watch?v=QcT5T-46iFA
8+
9+
**unsigned long long int** in C/C++: https://www.geeksforgeeks.org/maximum-value-of-unsigned-long-long-int-in-c/ (language specific). Implementations of **unsigned long long int** have a modulo behavior when performing arithmetic operations. Any arithmetic manipulation with unsigned long long int's will be taken modulo $2^{64}$ automatically.
10+
11+
## Solution
12+
Let's define:
13+
14+
F(n) = $a^n$ + $b^n$
15+
16+
=> F(0) = $a^0$ + $b^0$ = 2
17+
18+
=> F(1) = a + b = **p**
19+
20+
$a^2$ + $b^2$ = $(a+b)^2$ - 2ab
21+
22+
=> $a^2$ + $b^2$ = (a + b) * (a + b) - ab * ( $a^0$ + $b^0$ )
23+
24+
=> F(2) = $a^2$ + $b^2$ = **p** * (a + b) - **q** * ( $a^0$ + $b^0$ )
25+
26+
$a^3$ + $b^3$ = (a + b) * ( $a^2$ + $b^2$ ) - ab * (a + b)
27+
28+
=> F(3) = $a^3$ + $b^3$ = **p** * ( $a^2$ + $b^2$ ) - **q** * (a + b)
29+
30+
$a^4$ + $b^4$ = (a + b) * ( $a^3$ + $b^3$ ) - ab * ( $a^2$ + $b^2$ )
31+
32+
=> F(4) = $a^4$ + $b^4$ = **p** * ( $a^3$ + $b^3$ ) - **q** * ( $a^2$ + $b^2$ )
33+
34+
Observing the pattern we can conclude:
35+
36+
F(n) = **p** * F(n-1) - **q** * F(n-2)
37+
38+
It's a linear recurrence that can be solved using matrix exponentiation technique.
39+
40+
$$
41+
\begin{pmatrix}
42+
p & -q \\
43+
1 & 0
44+
\end{pmatrix}
45+
\begin{pmatrix}
46+
F(1) \\
47+
F(0)
48+
\end{pmatrix} =
49+
\begin{pmatrix}
50+
F(2) \\
51+
F(1)
52+
\end{pmatrix}
53+
$$
54+
55+
$$
56+
\begin{pmatrix}
57+
p & -q \\
58+
1 & 0
59+
\end{pmatrix} ^ {2}
60+
\begin{pmatrix}
61+
p \\
62+
2
63+
\end{pmatrix} =
64+
\begin{pmatrix}
65+
F(3) \\
66+
F(2)
67+
\end{pmatrix}
68+
$$
69+
70+
$$
71+
\begin{pmatrix}
72+
p & -q \\
73+
1 & 0
74+
\end{pmatrix} ^ {n}
75+
\begin{pmatrix}
76+
p \\
77+
2
78+
\end{pmatrix} =
79+
\begin{pmatrix}
80+
F(n+1) \\
81+
F(n)
82+
\end{pmatrix}
83+
$$
84+
85+
## Complexity
86+
- Time Complexity: O(T * $k^3$ $log{_2}{n}$). Here, k = 2
87+
- Memory Complexity: O( $k^2$ ).
88+
89+
## Code
90+
91+
### C++
92+
93+
```cpp
94+
#include <bits/stdc++.h>
95+
96+
using namespace std;
97+
98+
99+
typedef unsigned long long ull;
100+
101+
struct Matrix {
102+
vector <vector <ull>> mat;
103+
104+
Matrix(int n) {
105+
mat.assign(n, vector <ull> (n, 0));
106+
}
107+
};
108+
109+
Matrix mat_multiply(const Matrix& A, const Matrix& B) {
110+
int n = A.mat.size();
111+
Matrix res(n);
112+
113+
for(int i = 0; i < n; ++i) {
114+
for(int j = 0; j < n; ++j) {
115+
for(int k = 0; k < n; ++k) {
116+
res.mat[i][j] += A.mat[i][k] * B.mat[k][j];
117+
}
118+
}
119+
}
120+
121+
return res;
122+
}
123+
124+
Matrix binpow(Matrix &A, int power) {
125+
int n = A.mat.size();
126+
Matrix res(n);
127+
128+
for(int i = 0; i < n ; ++i) {
129+
for(int j = 0; j < n; ++j) {
130+
res.mat[i][j] = (i == j? 1:0); // identity matrix
131+
}
132+
}
133+
134+
while (power > 0) {
135+
if (power & 1) {
136+
res = mat_multiply(res, A);
137+
}
138+
power >>= 1;
139+
A = mat_multiply(A, A);
140+
}
141+
142+
return res;
143+
}
144+
145+
int main(int argc, const char *argv[]) {
146+
147+
// for fast I/O
148+
ios_base::sync_with_stdio(false);
149+
cin.tie(nullptr);
150+
151+
int t;
152+
cin >> t;
153+
154+
for(int ts = 1; ts <= t; ++ts) {
155+
ull p, q, n;
156+
cin >> p >> q >> n;
157+
158+
Matrix A(2);
159+
A.mat[0][0] = p;
160+
A.mat[0][1] = -q;
161+
A.mat[1][0] = 1;
162+
163+
A = binpow(A, n);
164+
165+
cout << "Case " << ts << ": " << A.mat[1][0]*p + (A.mat[1][1]<<1) << '\n';
166+
}
167+
168+
return 0;
169+
}
170+
```

0 commit comments

Comments
 (0)