Problem Inversions
Find the number of permutations of
Summary of my approach
Step 1
Figure it is called “mahonian triangle numbers”, either by using OEIS or by reading at the bottom of this wikipedia page inversions.
Step 2
Find the relationship with “Truncated Euler Product Triangle” from this paper.
You can basically write mahonian numbers as:
Step 3
Realize that if
Step 4
Since we want the answer modulus 2,
Step 5
Finally, if you generate p(c)
for c up to 100, you realize that it is very sparse!
1 -1 -1 0 0 1 0 1 0 0 0 0 -1 0 0 -1 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 ...
Doing some research, it turns out the non-zero indices are a series called Generalized Pentagonal Numbers and there is an efficient way to generate them one by one. Using Pentagonal Number Theorem, you can generate the non-zero indices. The k-th index
Code and Time Complexity
There are
Here is the code I submitted during the contest and below is a cleaned up version of it.
#include <iostream>
using namespace std;
typedef long long ll;
ll comb2(ll n, ll p) {
return (p & (n - p)) ? 0 : 1;
}
ll g(ll n) {
return (3 * n * n - n) / 2;
}
ll calc(ll r, ll c, ll n, ll num) {
return (2 + comb2(r + c - n, r) * (num % 2 == 0 ? 1 : -1) ) % 2;
}
ll mahonian(ll r, ll c) {
ll res = calc(r, c, 0, 0);
for (ll num = 1; ; num++) {
for (ll mul: {1, -1}) {
ll nxt = g(num * mul);
if (nxt >= c + 1) return res;
res = (res + calc(r, c, nxt, num)) % 2;
}
}
}
int main() {
ll tc, n, k;
cin >> tc;
while (tc--) {
cin >> n >> k;
cout << mahonian(n-1, k) << endl;
}
return 0;
}