康托展开与逆展开

康托展开用树状数组的优化版本

using ULL = unsigned long long;
const int N = 18;
ULL fact[N] = {1}, P[N], A[N], tree[N];
ULL lowbit(ULL x) { return x & -x; }
ULL query(ULL x) {
	ULL ans = 0;
	for (int i = x; i >= 1; i -= lowbit(i))
		ans += tree[i];
	return ans;
}
void update(ULL x, ULL d) {
	for (int i = x; i < N; i += lowbit(i))
		tree[i] += d;
}
ULL cantor(int P[], int n) {
	ULL ans = 1;
	for (int i = n; i >= 1; i--) {
		A[i] = query(P[i]);
		update(P[i], 1);
	}
	for (int i = 1; i < n; i++)
		ans = (ans + A[i] * fact[n - i]) % MOD;
	return ans;
}

康托逆展开

ULL fact[N] = {1, 1}, a[N];
void decantor(ULL a[], ULL k, ULL n) {
	int p[n+2];
	--k;
	std::vector<int> rem(n+2, 0);
	std::iota(rem.begin(), rem.end(), 1);
	for (ULL i = 1; i <= n; ++i) {
		p[i] = k / fact[n-i], k %= fact[n-i];
		a[i] = rem[p[i]];
		rem.erase(std::lower_bound(rem.begin(), rem.end(), a[i]));
	}
}
posted @ 2024-04-11 18:38  飞花阁  阅读(13)  评论(0)    收藏  举报
//雪花飘落效果