Search for a command to run...
Progressive hints first, then the full explanation and implementation when you're ready to cash out.
Review status
AI-generated and still unreviewed. Double-check the details before internalizing them.
Hints
Open only as much as you need to keep the solve alive.
Write the correctness as a sum of indicators over intervals. If is the number of palindromic subsegments, then The square means ordered pairs of intervals. Don’t accidentally count unordered pairs and nuke the answer.
A substring of length is a palindrome with probability So if two palindrome events are independent, their pair contribution is just the product of those two powers.
The dangerous-looking part is overlap. But overlap does not automatically mean dependence. Group symmetric positions inside each substring. For two substrings with different centers, the graph connecting their symmetry-groups through shared positions is a forest, so the probabilities still multiply.
Therefore the only dependent pairs are concentric substrings: same midpoint, one nested inside the other. If their radii are and , the larger palindrome implies the smaller one, so the true probability is instead of
Start with the fully independent answer , where Then add, for each center, Count these radius pairs by the value of , and the whole thing becomes linear.
Let
For a substring of length , being a palindrome forces exactly pairs of characters to be equal. So
Define
where is the indicator that interval is palindromic. We need
The whole problem is figuring out when two palindrome events are independent.
The Big Trick: Almost Everything Is Independent
For one interval, group positions that must be equal in a palindrome. For example, a length interval has groups: three symmetric pairs and the middle singleton. In general, a length palindrome has
free groups.
Now take two substrings and .
Make a bipartite graph:
If the two substrings have different centers, this graph is a forest. Why? Walking two steps in this graph corresponds to reflecting around one center, then reflecting around the other center. The composition of two different reflections is a nonzero translation. A nonzero translation cannot bring you back to the same position, so cycles are impossible. That is the clean version; the messy version is just the same fact wearing a fake mustache.
Let the lengths be and , and let their overlap length be .
For non-concentric substrings, the graph has
vertices and edges, so because it is a forest, it has
connected components. These components are exactly the final free color choices.
The union has positions, so the probability exponent is
That is exactly the product of the two individual probabilities.
So every non-concentric pair behaves independently. Even overlapping ones. That is the part that feels illegal, but it is true.
Only Same-Center Pairs Need Fixing
If two substrings have the same center, one is nested inside the other.
Represent a centered substring by its radius
A palindrome of larger radius automatically implies every smaller palindrome with the same center. Therefore, for two radii at the same center,
But if we first pretend everything is independent, that pair was counted as
So the correction for this ordered radius pair is
Base Independent Sum
Let
This is .
If all pairs were independent, the answer would be
Now add corrections for same-center pairs only.
Odd Centers
For a character center, allowed radii are
Here radius is the one-character substring, which is always a palindrome.
For all ordered pairs of radii in :
because the number of ordered pairs with is
Also,
So the odd-center correction is
Even Centers
For a gap center, allowed radii are
There is no radius substring because empty substrings do not count.
Similarly,
The count comes from
Putting It Together
For every character position , the maximum odd radius is
using zero-indexed positions.
For every gap after position and before position , the maximum even radius is
The answer is
All powers and sums are computed modulo . Since is prime and , the inverse exists.
Complexity
Precompute powers of , the two correction arrays, and then scan all centers.
Time:
per test case.
Memory:
Across all test cases, this is fine because the total is at most . The hard version looks scary, but once non-concentric pairs stop pretending to be a problem, it folds pretty cleanly.
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
ll modPow(ll a, ll e, ll mod) {
ll res = 1 % mod;
while (e > 0) {
if (e & 1) res = (ll)((__int128)res * a % mod);
a = (ll)((__int128)a * a % mod);
e >>= 1;
}
return res;
}
int main() {
setIO();
int T;
cin >> T;
while (T--) {
int n;
ll m, p;
cin >> n >> m >> p;
auto mul = [&](ll a, ll b) -> ll {
return (ll)((__int128)a * b % p);
};
ll q = modPow(m % p, p - 2, p);
vector<ll> pw(n + 1, 1);
for (int i = 1; i <= n; i++) pw[i] = mul(pw[i - 1], q);
ll mean = 0;
for (int len = 1; len <= n; len++) {
mean += mul(n - len + 1, pw[len / 2]);
if (mean >= p) mean -= p;
}
int maxR = n / 2;
vector<ll> oddCorr(maxR + 1), evenCorr(maxR + 1);
ll sum = 0, byMax = 0;
for (int r = 0; r <= maxR; r++) {
sum += pw[r];
if (sum >= p) sum -= p;
byMax = (byMax + mul(2LL * r + 1, pw[r])) % p;
oddCorr[r] = (byMax - mul(sum, sum) + p) % p;
}
sum = 0;
byMax = 0;
evenCorr[0] = 0;
for (int r = 1; r <= maxR; r++) {
sum += pw[r];
if (sum >= p) sum -= p;
byMax = (byMax + mul(2LL * r - 1, pw[r])) % p;
evenCorr[r] = (byMax - mul(sum, sum) + p) % p;
}
ll correction = 0;
for (int i = 0; i < n; i++) {
int r = min(i, n - 1 - i);
correction += oddCorr[r];
correction %= p;
}
for (int gap = 1; gap <= n - 1; gap++) {
int r = min(gap, n - gap);
correction += evenCorr[r];
correction %= p;
}
ll ans = (mul(mean, mean) + correction) % p;
cout << ans << '\n';
}
}#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
ll modPow(ll a, ll e, ll mod) {
ll res = 1 % mod;
while (e > 0) {
if (e & 1) res = (ll)((__int128)res * a % mod);
a = (ll)((__int128)a * a % mod);
e >>= 1;
}
return res;
}
int main() {
setIO();
int T;
cin >> T;
while (T--) {
int n;
ll m, p;
cin >> n >> m >> p;
auto mul = [&](ll a, ll b) -> ll {
return (ll)((__int128)a * b % p);
};
ll q = modPow(m % p, p - 2, p);
vector<ll> pw(n + 1, 1);
for (int i = 1; i <= n; i++) pw[i] = mul(pw[i - 1], q);
ll mean = 0;
for (int len = 1; len <= n; len++) {
mean += mul(n - len + 1, pw[len / 2]);
if (mean >= p) mean -= p;
}
int maxR = n / 2;
vector<ll> oddCorr(maxR + 1), evenCorr(maxR + 1);
ll sum = 0, byMax = 0;
for (int r = 0; r <= maxR; r++) {
sum += pw[r];
if (sum >= p) sum -= p;
byMax = (byMax + mul(2LL * r + 1, pw[r])) % p;
oddCorr[r] = (byMax - mul(sum, sum) + p) % p;
}
sum = 0;
byMax = 0;
evenCorr[0] = 0;
for (int r = 1; r <= maxR; r++) {
sum += pw[r];
if (sum >= p) sum -= p;
byMax = (byMax + mul(2LL * r - 1, pw[r])) % p;
evenCorr[r] = (byMax - mul(sum, sum) + p) % p;
}
ll correction = 0;
for (int i = 0; i < n; i++) {
int r = min(i, n - 1 - i);
correction += oddCorr[r];
correction %= p;
}
for (int gap = 1; gap <= n - 1; gap++) {
int r = min(gap, n - gap);
correction += evenCorr[r];
correction %= p;
}
ll ans = (mul(mean, mean) + correction) % p;
cout << ans << '\n';
}
}