洛谷 P3477 [POI2008]PER-Permutation 解题报告
P3477 [POI2008]PER-Permutation
题目描述
Multiset is a mathematical object similar to a set, but each member of a multiset may have more than one membership.
Just as with any set, the members of a multiset can be ordered in many ways. We call each such ordering a permutation of the multiset. For example, among the permutations of the multiset{1,1,2,3,3,3,7,8}. there are {2,3,1,3,3,7,1,8} and{8,7,3,3,3,2,1,1}.
We will say that one permutation of a given multiset is smaller (in lexicographic order) than another permutation, if on the first position that does not match the first permutation has a smaller element than the other one. All permutations of a given multiset can be numbered (starting from one) in an increasing order.
Task Write a programme that reads the description of a permutation of a multiset and a positive integerm from the standard input, determines the remainder of the rank of that permutation in the lexicographic ordering modulo m, writes out the result to the standard output.
多重集合是数学中的一个概念,它的定义很像集合,但是在多重集之中,同一个元素可以出现多次。
和集合一样,多重集的的元素可以有很多种元素的排布顺序。我们把它叫作多重集的排列。
现在我们定义多重集的某个排列\(s_i\)比某个排列\(s_j\)的大小比较为字典序比较。这样某个多重集的排列可以从小到大得排起来。
现在给你一个元素个数为n的多重集的一个排列和\(m\),求这个排列的排名取模\(m\)。
输入输出格式
输入格式:
The first line of the standard input holds two integers n( \(1\le n \le 300000\)) and m ( \(2 \le m \le 10^9\)) ,separated by a single space. These denote, respectively, the cardinality of the multiset and \dots\ the number m.
The second line of the standard input contains n positive integers \(a_i\) (\(1\le a_i \le 300000\)), separated by single spaces and denoting successive elements of the multiset permutation.
第一行 两个整数n,m
第二行 n个数,代表多重集的排列
输出格式:
The first and only line of the standard output is to hold one integer, the remainder modulo m of the rank of the input permutation in the lexicographic ordering.
一行一个整数 排名取模m
一句话题意:求有重复元素的排列的排名,模数不一定是质数
我们找到字典序比它小的排列的个数
讨论每一位数值的贡献,像康托展开那样
设给出排列为 \(a_1,a_2,a_3,...a_n\),字典序比它小的排列为\(b_1,b_2,b_3,...b_n\)
考虑从左到右第\(i\)位的贡献
若\(b_i=a_i\) 右边的是子问题
若\(b_i<a_i\),则设右边的从小到大每个元素出现的次数分别为\(c_1,c_2,...,c_m\)
若\(b_i\)出现\(c_j\)次
则当\(b_i\)这个数值放在第\(i\)位置,右边的全排列的贡献为
\(\frac{(n-i)!}{c_1! \times c_2 ! \times ... \times c_m!} \times c_j\)
则所有可以放到第一位的数的贡献和为
\(\frac{(n-i)!}{c_1! \times c_2 ! \times ... \times c_m!} \times \sum_{b_i<a_i}c_j\)(\(b_i\)这里代表数值意义,一个数值只出现一次)
我们处理每一位这样的
后面的好处理,树状数组维护一下就行了
前面的因为模数不为质数可能没有逆元,所有我们先把模数唯一分解,对每一个质因子的多少次方做,然后CRT进行合并
在某个质因子多少次方下做时,我们把数字拆成 其他项 和 这个质因子多少次方 就行了
因为答案一定是整数,所以分子的质因子个数一定大于分母的,我们把这些先拿出来,就可以求逆元啦,然后快速幂乘回去就行
注意小细节
Code:
#include <cstdio>
#include <cstring>
#define ll long long
const int N=3e5+10;
ll a[N],m,n,buct[N],id[N],cnt0[N];
ll fac[N],ct[N],mx,sum[N],mod;
void exgcd(ll a,ll b,ll &x,ll &y)//只是一个exgcd..
{
if(!b){x=1,y=0;return;}
exgcd(b,a%b,x,y);
ll tmp=x;
x=y;
y=tmp-a/b*y;
}
ll inv(ll a,ll p)//只是一个求逆元
{
ll x,y;
exgcd(a,p,x,y);
return (x%p+p)%p;
}
ll CRT(ll a,ll b)//只是CRT的一项
{
return mod/b*a%mod*inv(mod/b,b)%mod;
}
ll quick_pow(ll d,ll k,ll p)//只是一个快速幂
{
ll f=1;
while(k)
{
if(k&1) f=f*d%p;
d=d*d%p;
k>>=1;
}
return f;
}
ll query(ll x)
{
ll s;for(s=0;x;x-=x&-x) s+=sum[x];
return s;
}
void add(ll x)
{
while(x<=m) ++sum[x],x+=x&-x;
}
ll cal(ll d,ll p)
{
ll ans=0;fac[0]=1;
memset(ct,0,sizeof(ct));
for(ll i=1;i<=mx;i++)
{
ll num=i;
while(num%d==0) num/=d;
(fac[i]=fac[i-1]*num%p)%=p;
for(ll j=i;j;j/=d) ct[i]+=j/d;
}
memset(cnt0,0,sizeof(cnt0));
memset(sum,0,sizeof(sum));
cnt0[a[n]]++;add(a[n]);
ll den=1,cn=0;
for(ll i=n-1;i;i--)
{
ll cc=++cnt0[a[i]];
add(a[i]);
if(cc>1)
{
(den*=fac[cc-1]*inv(fac[cc],p)%p)%=p;
cn+=ct[cc]-ct[cc-1];
}
ll k=query(a[i]-1);
(ans+=fac[n-i]*den%p*k%p*(k?quick_pow(d,ct[n-i]-cn,p):0)%p)%=p;
}
return ans;
}
ll calp(ll p)
{
ll ans=0;
fac[0]=1;
for(ll i=1;i<=mx;i++)
fac[i]=(fac[i-1]*i)%p;
memset(cnt0,0,sizeof(cnt0));
memset(sum,0,sizeof(sum));
cnt0[a[n]]++;add(a[n]);
ll den=1;
for(ll i=n-1;i;i--)
{
ll cc=++cnt0[a[i]];
add(a[i]);
if(cc>1) (den*=fac[cc-1]*inv(fac[cc],p)%p)%=p;
(ans+=fac[n-i]*den%p*query(a[i]-1)%p)%=p;
}
return ans;
}
ll work(ll p)
{
ll ans=0;
for(ll i=2;i*i<=p;i++)
{
if(p%i==0)
{
ll d=1;
while(p%i==0)
p/=i,d*=i;
if(i==d)
(ans+=CRT(calp(i)+1,p))%=mod;
else
(ans+=CRT(cal(i,d)+1,d))%=mod;
}
}
if(p!=1) (ans+=CRT(calp(p)+1,p))%=mod;
return ans;
}
int main()
{
//freopen("data.in","r",stdin);
scanf("%lld%lld",&n,&mod);
for(ll i=1;i<=n;i++) scanf("%lld",a+i),buct[a[i]]++;
for(ll i=1;i<=N-10;i++) if(buct[i]) id[i]=++m;
for(ll i=1;i<=n;i++)
{
mx=mx>buct[a[i]]?mx:buct[a[i]];
a[i]=id[a[i]];
}
mx=mx>n?mx:n;
printf("%lld\n",work(mod));
return 0;
}
2018.8.27
洛谷 P3477 [POI2008]PER-Permutation 解题报告的更多相关文章
- 洛谷_Cx的故事_解题报告_第四题70
1.并查集求最小生成树 Code: #include <stdio.h> #include <stdlib.h> struct node { long x,y,c; ...
- 洛谷 P2317 [HNOI2005]星际贸易 解题报告
P2317 [HNOI2005]星际贸易 题目描述 输入输出格式 输入格式: 输出格式: 如果可以找到这样的方案,那么输出文件output.txt中包含两个整数X和Y.X表示贸易额,Y表示净利润并且两 ...
- 洛谷 P3802 小魔女帕琪 解题报告
P3802 小魔女帕琪 题目背景 从前有一个聪明的小魔女帕琪,兴趣是狩猎吸血鬼. 帕琪能熟练使用七种属性(金.木.水.火.土.日.月)的魔法,除了能使用这么多种属性魔法外,她还能将两种以上属性组合,从 ...
- 洛谷 P2606 [ZJOI2010]排列计数 解题报告
P2606 [ZJOI2010]排列计数 题目描述 称一个\(1,2,...,N\)的排列\(P_1,P_2...,P_n\)是\(Magic\)的,当且仅当对所以的\(2<=i<=N\) ...
- 洛谷1303 A*B Problem 解题报告
洛谷1303 A*B Problem 本题地址:http://www.luogu.org/problem/show?pid=1303 题目描述 求两数的积. 输入输出格式 输入格式: 两个数 输出格式 ...
- 洛谷 P3084 [USACO13OPEN]照片Photo 解题报告
[USACO13OPEN]照片Photo 题目描述 农夫约翰决定给站在一条线上的\(N(1 \le N \le 200,000)\)头奶牛制作一张全家福照片,\(N\)头奶牛编号\(1\)到\(N\) ...
- 洛谷 P1379 八数码难题 解题报告
P1379 八数码难题 题目描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给出一种初始布局(初 ...
- NOIP2015 D2T3 洛谷2680 BZOJ4326 运输计划 解题报告
前言:个人认为这是历年NOIP中比较简单的最后一题了,因此将自己的思路与大家分享. 题目大意: 给一棵无根树,给出m条路径.允许将树上的一条边的权值改为0.求m条路径长度最大值的最小值.n,m< ...
- 洛谷 P1129 [ZJOI2007]矩阵游戏 解题报告
P1129 [ZJOI2007]矩阵游戏 题目描述 小\(Q\)是一个非常聪明的孩子,除了国际象棋,他还很喜欢玩一个电脑益智游戏――矩阵游戏.矩阵游戏在一个\(N*N\)黑白方阵进行(如同国际象棋一般 ...
随机推荐
- 在pythonanywhere上部署Django应用
参考:https://tutorial.djangogirls.org/zh/deploy/ 资料讲的很明了,仅在设置上做几点补充. 1.设置相对路径 import os BASE_DIR = os. ...
- Ubuntu14.04安装opencv2.4.13
本文参考相关链接:http://blog.csdn.net/honyniu/article/details/46390097 系 统:Ubuntu 14.04 x64 opencv版本:2.4.1 ...
- TRANSLATE(转换大/小写并替换字符)
可以将字母 转换大/小 写或使用替 换规则. 要转换大/小 写,请使用 TRANSLATE 语句,用法 如下: 语法 TRANSLATE <c> TO UPPER CASE. TRANSL ...
- 【SAPUI5】ODataを構成するもの
はじめに SAPUI5でアプリケーションを作るにあたり.ODataは避けては通れないトピックです.結構広いテーマなので.5-7回くらいに分けて書きたいと思います.1回目はODataの概要について説明し ...
- linux安装软件的几种方式(kali平台)和一些实用的软件(持续更新)
安装软件前我们先更改镜像源,编辑 /etc/apt/sources.list 文件, 在文件最前面添加以下条目: #中科大更新源 deb https://mirrors.ustc.edu.cn/kal ...
- 【转】mui 通过JSON动态的生成列表
<script type="text/template" id="radio-tigan"> <%for(var i=0;i<recor ...
- 问题:调用 ASP.Net Core WebAPI的HTTP POST方法时,从 [FromBody] 中读取的 MongoDB GeoJsonObjectModel成员总是null
问题描述: POST/PUT to ASP.Net Core with [FromBody] to a MongoDB GeoJsonObjectModel member is always null ...
- ibdata1文件损坏时恢复InnoDB单表测试
Preface ibdata1 file is a shared system tablespace of innodb engine.Although we always set v ...
- Ubuntu下使用Git_2
接着上一篇的写,这里练习一下git clone 指令 指令格式 $ git clone <repository> <directory> <respository> ...
- No resources found. Error from server (NotAcceptable): unknown (get pods)
问题:正确安装kubectl后,可查询到当前使用集群服务,也可切换不同的集群,但无法获取当前运行的pods的信息与所有的service,具体表现为 $ kubectl get po -nwx No r ...