康拓展开和逆康拓展开
Posted fanshhh
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了康拓展开和逆康拓展开相关的知识,希望对你有一定的参考价值。
康拓展开和逆康拓展开
复杂度O(\(n^2\))的会tle(看数据就知道了)(虽然某题解说可以,不知道是不是后期加强了数据
然而我还是写了O(\(n^2\))的
#include <cstdio>
typedef long long LL;
LL f[1000010];
const LL mod = 998244353;
int a[1000010], b[1000010];
int main()
f[0] = 1;
for(int i = 1; i < 1000005; i++) f[i] = f[i-1] * i % mod;
int n;
while(~scanf("%d", &n))
for(int i = 0; i < n; i++)
scanf("%d", &a[i]);
b[a[i]] = 0;
LL ans = 1, cnt;
for(int i = 0; i < n; i++)
cnt = 0;
for(int j = 1; j < a[i]; j++)
if(b[j] == 0) cnt++;
b[a[i]] = 1;
ans = ans % mod + cnt * f[n - i - 1];
printf("%lld\n", ans % mod);
return 0;
下面这个是树状数组实现的,复杂度O(nlogn) (能过)
#include <cstdio>
typedef long long LL;
LL f[1000010];
const LL mod = 998244353;
int a[1000010], n, bit[1000010];
void add(int i, int x)
while(i <= n)
bit[i] += x;
i += i & (-i);
int query(int i)
int res = 0;
while(i > 0)
res += bit[i];
i -= i & (-i);
return res;
int main()
f[0] = 1;
for(int i = 1; i < 1000005; i++) f[i] = f[i-1] * i % mod;
scanf("%d", &n);
for(int i = 1; i <= n; i++)
scanf("%d", &a[i]);
add(a[i], 1);
LL ans = 1, cnt;
for(int i = 1; i <= n; i++)
add(a[i], -1);
cnt = query(a[i]);
ans = ans % mod + cnt * f[n - i];
printf("%lld\n", ans % mod);
return 0;
逆康拓展开O(\(n^2\))
#include <cstdio>
#include <cstring>
int main()
int n, k, f[15], b[15];
f[0] = 1;
for(int i = 1; i < 11; i++) f[i] = f[i-1] * i;
while(~scanf("%d %d", &n, &k))
memset(b, 0, sizeof(b));
k--;
for(int i = n - 1; i >= 0; i--)
int ans = k / f[i], cnt = 0;
for(int j = 1; j <= n; j++)
if(cnt == ans && b[j] == 0)
b[j] = 1;
printf("%d ", j);
break;
if(b[j] == 0) cnt++;
k = k % f[i];
printf("\n");
return 0;
复杂度更低的我还不会 呜呜我好菜
以上是关于康拓展开和逆康拓展开的主要内容,如果未能解决你的问题,请参考以下文章