ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

康托展开

2022-04-20 19:33:38  阅读:139  来源: 互联网

标签:le return int sum tree add 展开 康托


公式:\(a_{n}*(n-1)!+a_{n-1}*(n-2)!+……+a_{1}*0!\)
题目:
洛谷P5367 【模板】康托展开
题目描述
求 \(1\sim N\) 的一个给定全排列在所有 \(1\sim N\) 全排列中的排名。结果对 \(998244353\) 取模。

输入格式
第一行一个正整数 \(N\)。

第二行 \(N\) 个正整数,表示 \(1\sim N\) 的一种全排列。

输出格式
一行一个非负整数,表示答案对 \(998244353\) 取模的值。

输入输出样例
输入
3
2 1 3
输出
3
输入
4
1 2 4 3
输出
2
说明/提示
对于\(10\%\)数据,\(1\le N\le 10\)。
对于\(50\%\)数据,\(1\le N\le 5000\)。
对于\(100\%\)数据,\(1\le N\le 1000000\)。
对于这道题,康托展开的公式中\(a[i]\)是数列中从后往前数第\(1\sim i-1\)个数中比第i个数小的数的个数,整个运算过程也都是从后往前进行。
证明:
数列的第一个数,即最后一个被运算的数,当这个位置被确定时,后面的排列还有\((n-1)!\)种方式,而确保排在这种排列前面的排列一定是数比这个数小的数,共\(a[n]\)个,即它一定排在\(a[n]*(n-1)!\)种排列方式后,计算下一个位置时,同理,但因为前面的数已经确定了,所以\(a[i]\)只考虑它后面的数,其中求比这位数小数的个数可以用权值线段树。
代码:

#include<iostream>
#define mod 998244353
#define int long long
using namespace std;
int n;
int a[1000010];
struct node{
	int l,r;
	int sum;
}tree[4000010];
int tot=1;
void build(int i,int l,int r){
	tree[i].l=l;
	tree[i].r=r;
	if(l==r){
		tree[i].sum=0;
		return ;
	}
	int mid=(l+r)/2;
	build(i*2,l,mid);
	build(i*2+1,mid+1,r);
	tree[i].sum=0;
}
void add(int i,int p){
	tree[i].sum++;
	if(tree[i].l==tree[i].r){
		return ;
	}
	if(tree[i*2].r>=p){
		add(i*2,p);
	}
	else{
		add(i*2+1,p);
	}
	return ;
}
int search(int i,int l,int r){
	if(tree[i].l>=l&&tree[i].r<=r){
		return tree[i].sum;
	}
	if(tree[i].r<l||tree[i].l>r){
		return 0;
	}
	int s=0;
	if(tree[i*2].r>=l){
		s+=search(i*2,l,r);
	}
	if(tree[i*2+1].l<=r){
		s+=search(i*2+1,l,r);
	}
	return s;
}
int ans=0;
signed main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	build(1,1,n);
	for(int i=n-1;i>=1;i--){
		add(1,a[i+1]);
		tot=tot*(n-i)%mod;
		ans=(ans+tot*search(1,1,a[i]-1)%mod)%mod;
	}
	cout<<ans+1;
	return 0;
} 

标签:le,return,int,sum,tree,add,展开,康托
来源: https://www.cnblogs.com/z-2-we/p/16171342.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有