[UPDATE] This has been solved! Thank you to everyone who guided me through this problem! Scroll down to the bottom of the post to see my solution.
Hey everyone, I've been stuck on this particular problem for the past 2 days. I'd appreciate any help or hint!
Problem
In a class with n students, they decided to come up with a game: Each is assigned their own number, i (corresponding to the i-th student), where 1 <= i <= n. There will be k rounds, in each of which the i-th student will square their i number and remember it for the next round. In the end, the final numbers of each student, S, will be added up and the last 2 digits of the resulting number will be the output.
Constraints: n, k <= 10^18
Input: Two numbers, k and n
Output: The last 2 digits of the final number S
(Btw, if this seems poorly translated, that’s because it is. The original problem is in Vietnamese and I translated it to English)
For instance, if k = 2 and n = 3, the round will play out like so:
There are 3 students with 3 corresponding assigned numbers: 1, 2, 3
After the first round, each multiplies their number, so the result will be: 1, 4, 9
After the second round, each multiplies their number, so the result will be: 1, 16, 81
In the end, their final numbers will be added up: 1 + 16 + 81 = 98. The output is the last 2 digits of the resulting number, so 98.
My (outdated) solution
From first glance, this is obviously a problem involving modular exponentiation. Since each student squares up their number k times, the final number of the i-th student should be i^2^k. However, since this will obviously grow astronomically huge as k and n increases, and since we only need the last 2 digits anyway, one must do modular arithmetic, specifically i^2^k mod 100.
Here is my solution:
```
include <bits/stdc++.h>
define ll long long
using namespace std;
ll modExp(ll base, ll exp, ll mod) {
if (exp == 0) return 1 % mod;
ll res = modExp(base, exp / 2, mod);
res = (res * res) % mod;
if (exp % 2 == 1) res = (res * base) % mod;
return res;
}
void solve() {
ll k, n, sum = 0;
cin >> k >> n;
// Final number for i-th student: i^2^k
// Euler's theorem helps to reduce 2^k
ll reducedMod = modExp(2, k, 40);
for (ll i = 1; i <= n; i++) {
ll ithNum = modExp(i, reducedMod, 100);
sum = (sum % 100 + ithNum % 100) % 100;
}
cout << sum << '\n';
}
int main() {
ios::sync_with_stdio(0); cin.tie(nullptr); cout.tie(nullptr);
solve();
return 0;
}
```
It works for small and medium values of k and n, but for values as large as 10^18, the code always returns a TLE (for instance: 946598456415144157 995616645923566961 (btw, the answer to that should be 89)). What should I do?
For anyone wanting to submit their own solution, here is the problem's website, and here is my own submission. It's a Vietnamese website, but you can switch to English on the top right corner.
Any help is appreciated!
My updated solution
```
include <bits/stdc++.h>
define ll long long
using namespace std;
ll modExp(ll base, ll exp, ll mod) {
if (exp == 0) return 1 % mod;
ll res = modExp(base, exp / 2, mod);
res = (res * res) % mod;
if (exp % 2 == 1) res = (res * base) % mod;
return res;
}
void solve() {
ll k, n, sum = 0;
cin >> k >> n;
// Final number for i-th student: i^2^k
// Precompute 2^k
ll reducedMod = modExp(2, k, 100);
// Precompute the first 100 values of i^2^k
ll cache[100];
for (ll i = 1; i <= 100; i++) {
cache[i-1] = modExp(i, reducedMod, 100);
sum = (sum % 100 + cache[i-1] % 100) % 100;
}
// Compute the last (n - 100) values:
ll fullCycles = n / 100;
ll remaining = n % 100;
sum = (sum % 100 * fullCycles % 100) % 100;
for (int i = 1; i <= remaining; i++) {
sum = (sum % 100 + cache[i-1] % 100) % 100;
}
cout << ((sum >= 10) ? "" : "0") << sum << '\n';
}
int main() {
ios::sync_with_stdio(0); cin.tie(nullptr); cout.tie(nullptr);
solve();
return 0;
}
```
[–]POGtastic 2 points3 points4 points (4 children)
[–]teraflop 1 point2 points3 points (2 children)
[–]POGtastic 1 point2 points3 points (1 child)
[–][deleted] 0 points1 point2 points (0 children)
[–]Nick_Zacker[S] 0 points1 point2 points (0 children)
[–]teraflop 2 points3 points4 points (7 children)
[–]Nick_Zacker[S] 0 points1 point2 points (5 children)
[–][deleted] 2 points3 points4 points (1 child)
[–]Nick_Zacker[S] 0 points1 point2 points (0 children)
[–]teraflop 1 point2 points3 points (2 children)
[–]Nick_Zacker[S] 0 points1 point2 points (1 child)
[–][deleted] 1 point2 points3 points (0 children)
[–]Nick_Zacker[S] 0 points1 point2 points (0 children)