【题解】康拓展开(养生题)
【题解】康拓展开(养生题)
养生养生
编号 | 题目 | 状态 | 分数 | 总时间 | 内存 | 代码 / 答案文件 | 提交者 | 提交时间 |
---|---|---|---|---|---|---|---|---|
#528662 | #167. 康托展开 | Accepted | 100 | 1129 ms | 8060 K | C++ 11 (Clang) / 1.2 K | winlere | 2019-07-17 8:29:28 |
假如说我的排列是这样的
\[2 \quad3 \quad4\quad5\quad1
\]
可以从左往右扫,扫到第一个时,发现这个位置不是\(1\),而是\(2\),说明至少经历了\((2-1)\times (5-1)!\)次排列才可能第一个是\(2\)。把第一个判断完之后,就剩下了一个子排列,是个子问题。不过要动态维护每个数在当前剩下的数的排名,开个值域线段树就好了。
//@winlere
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std; typedef long long ll;
inline int qr(){
register int ret=0,f=0;
register char c=getchar();
while(c<48||c>57)f|=c==45,c=getchar();
while(c>=48&&c<=57) ret=ret*10+c-48,c=getchar();
return f?-ret:ret;
}
const int mod=998244353;
const int maxn=1e6+5;
int jc[maxn],n;
int data[maxn];
#define lowbit(x) ((x)&(-(x)))
inline void add(const int&pos,const int&ad){
for(register int t=pos;t<=n;t+=lowbit(t))
data[t]=data[t]+ad;
}
inline int q(const int&pos){
register ll ret=0;
for(register int t=pos;t;t-=lowbit(t))
ret+=data[t];
return ret;
}
inline void add(const int&l,const int&r,const int&ad){
if(l>r)return;
add(l,ad);add(r+1,-ad);
}
int main(){
int ans=1;
n=qr();
jc[0]=1;
for(register int t=1;t<=n;++t)
jc[t]=1ll*jc[t-1]*t%mod;
for(register int t=1;t<=n;++t)
add(t,t,t);
for(register int t=1,t1;t<=n;++t){
t1=qr();
ans=(ans+1ll*(q(t1)-1)*jc[(n-t)]%mod)%mod;
add(t1+1,n,-1);
}
printf("%d\n",ans);
return 0;
}
博客保留所有权利,谢绝学步园、码迷等不在文首明显处显著标明转载来源的任何个人或组织进行转载!其他文明转载授权且欢迎!