思路:

先copy一下百度百科 作为预备知识吧
多重全排列定义:求r1个1,r2个2,…,rt个t的排列数,设r1+r2+…+rt=n,设此排列数称为多重全排列,表示为$P(n;r1,r2,…,rt)$
$P(n;r1,r2,…,rt)=\frac{n!}{(r1!r2!...rt!)}$

题目是让求s的排名mod m
我们就可以从前往后枚举
前$(i-1)$位跟给出的排列一样 第i位填小于s[i]的数
后面i到n位可以随便填的方案数
(有点像数位DP最后统计的那种感觉.)
设calc[x]是串s中i到n位 x出现的次数
这样枚举到第i位的答案就是$(\Sigma_{j=i}^n{s[j]<s[i]})*\frac{(n-i)!}{(cnt[1]!cnt[2]!...cnt[max—s[x]])}$
(离散化什么的就不用我说了吧)
m不是质数 怎么办
把m拆成$m={p_{1}}^{q_{1}}*{p_{2}}^{q_{2}}...{p_{cnt}}^{q_{cnt}}$
用中国剩余定理搞一搞
把不与$p^q$互质的数单独拎出来算
整体复杂度是$O(nlognlogm)$的
(最好别用线段树.. 常数大)
(CRT和exgcd的时候要时刻注意负数)

//By SiriusRen
#include <cstdio>
#include <algorithm>
using namespace std;
const int N=;
int n,M,u,xx,yy,s[N],cpy[N],tree[N*],Ans[N];
int p[N],ps[N],cnt,fac[N],numb[N],calc[N],pw[N];
void exgcd(int a,int b,int &x,int &y){
if(!b){x=,y=;return;}
exgcd(b,a%b,x,y);
int temp=x;x=y;y=temp-a/b*y;
}
int CRT(int *a,int *m){
int ans=;
for(int i=;i<=cnt;i++){
exgcd(M/m[i],m[i],xx,yy);
ans=(ans+1ll*M/m[i]*xx%M*a[i])%M;
}return (ans+M)%M;
}
void insert(int l,int r,int pos,int num,int wei){
if(l==r){tree[pos]+=wei;return;}
int mid=(l+r)>>,lson=pos<<,rson=pos<<|;
if(mid<num)insert(mid+,r,rson,num,wei);
else insert(l,mid,lson,num,wei);
tree[pos]=tree[lson]+tree[rson];
}
int query(int l,int r,int pos,int L,int R){
if(l>=L&&r<=R)return tree[pos];
int mid=(l+r)>>,lson=pos<<,rson=pos<<|;
if(mid<L)return query(mid+,r,rson,L,R);
else if(mid>=R)return query(l,mid,lson,L,R);
else return query(l,mid,lson,L,R)+query(mid+,r,rson,L,R);
}
void Dec(int m){
for(int i=;i*i<=m;i++)if(m%i==){
p[++cnt]=i,ps[cnt]=;
while(m%i==)m/=i,ps[cnt]*=i;
}if(m!=)p[++cnt]=m,ps[cnt]=m;
}
int inv(int a,int b){exgcd(a,b,xx,yy);return (xx+b)%b;}
void solve(){
for(int T=;T<=cnt;T++){
for(int i=;i<=n;i++){
int temp=i,jy=;while(temp%p[T]==)temp/=p[T],jy++;
fac[i]=1ll*fac[i-]*temp%ps[T];
pw[i]=pw[i-]*p[T]%ps[T];
numb[i]=numb[i-]+jy;
insert(,u,,s[i],),calc[s[i]]++;
}int sum=,sum_inv=;
for(int i=;i<=u;i++)sum+=numb[calc[i]],sum_inv=1ll*sum_inv*inv(fac[calc[i]],ps[T])%ps[T];
for(int i=;i<=n;i++){
Ans[T]=(Ans[T]+1ll*query(,u,,,s[i]-)*fac[n-i]%ps[T]*sum_inv%ps[T]*pw[numb[n-i]-sum])%ps[T];
sum_inv=1ll*sum_inv*fac[calc[s[i]]]%ps[T]*inv(fac[calc[s[i]]-],ps[T])%ps[T];
sum-=numb[calc[s[i]]],calc[s[i]]--,sum+=numb[calc[s[i]]];
insert(,u,,s[i],-);
}(Ans[T]+=)%=ps[T];
}
}
signed main(){
scanf("%d%d",&n,&M);Dec(M);pw[]=fac[]=;
for(int i=;i<=n;i++)scanf("%d",&s[i]),cpy[i]=s[i];
sort(cpy+,cpy++n);u=unique(cpy+,cpy++n)-cpy-;
for(int i=;i<=n;i++)s[i]=lower_bound(cpy+,cpy++u,s[i])-cpy;
solve();printf("%d\n",CRT(Ans,ps));
}

BZOJ 1129 exgcd+CRT+线段树的更多相关文章

  1. Bzoj 2752 高速公路 (期望,线段树)

    Bzoj 2752 高速公路 (期望,线段树) 题目链接 这道题显然求边,因为题目是一条链,所以直接采用把边编上号.看成序列即可 \(1\)与\(2\)号点的边连得是. 编号为\(1\)的点.查询的时 ...

  2. BZOJ.3938.Robot(李超线段树)

    BZOJ UOJ 以时间\(t\)为横坐标,位置\(p\)为纵坐标建坐标系,那每个机器人就是一条\(0\sim INF\)的折线. 用李超线段树维护最大最小值.对于折线分成若干条线段依次插入即可. 最 ...

  3. BZOJ.1558.[JSOI2009]等差数列(线段树 差分)

    BZOJ 洛谷 首先可以把原序列\(A_i\)转化成差分序列\(B_i\)去做. 这样对于区间加一个等差数列\((l,r,a_0,d)\),就可以转化为\(B_{l-1}\)+=\(a_0\),\(B ...

  4. BZOJ 3779: 重组病毒(线段树+lct+树剖)

    题面 escription 黑客们通过对已有的病毒反编译,将许多不同的病毒重组,并重新编译出了新型的重组病毒.这种病毒的繁殖和变异能力极强.为了阻止这种病毒传播,某安全机构策划了一次实验,来研究这种病 ...

  5. BZOJ 3123 森林(函数式线段树)

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=3123 题意: 思路:总的来说,查询区间第K小利用函数式线段树的减法操作.对于两棵树的合并 ...

  6. BZOJ 2124等差子序列 线段树&&hash

    [题目描述 Description] 给一个 1 到 N 的排列{Ai},询问是否存在 1<=p1<p2<p3<p4<p5<…<pLen<=N(Len& ...

  7. Bzoj 3747: [POI2015]Kinoman 线段树

    3747: [POI2015]Kinoman Time Limit: 60 Sec  Memory Limit: 128 MBSubmit: 553  Solved: 222[Submit][Stat ...

  8. BZOJ 3155: Preprefix sum( 线段树 )

    刷刷水题... 前缀和的前缀和...显然树状数组可以写...然而我不会, 只能写线段树了 把改变成加, 然后线段树维护前缀和, 某点p加, 会影响前缀和pre(x)(p≤x≤n), 对[p, n]这段 ...

  9. bzoj 1307/1318 玩具 线段树+记录时间戳

    玩具 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 743  Solved: 404[Submit][Status][Discuss] Descrip ...

随机推荐

  1. 为什么要有uboot?带你全面分析嵌入式linux系统启动过程中uboot的作用

    1.为什么要有uboot 1.1.计算机系统的主要部件 (1)计算机系统就是以CPU为核心来运行的系统.典型的计算机系统有:PC机(台式机+笔记本).嵌入式设备(手机.平板电脑.游戏机).单片机(家用 ...

  2. 洛谷 2055 BZOJ 1433 [ZJOI2009]假期的宿舍

    [题解] 既然是一人对应一床,那么显然可以用二分图匹配来做.俩人认识的话,如果其中一个a是在校学生,另一个b不回家,b就可以向a的床连边(a,b当然也可以是同一个人). 然后如果最大匹配数大于等于需要 ...

  3. ACM-ICPC 2018 徐州赛区网络预赛 J. Maze Designer

    传送门:https://nanti.jisuanke.com/t/31462 本题是一个树上的问题:结点间路径问题. 给定一个有N×M个结点的网格,并给出结点间建立墙(即拆除边)的代价.花费最小的代价 ...

  4. Python异常捕捉的一个小问题

    问题: names = ['taotao','songwenjing','liu','li']I = iter(names)while True: try: s = next(I) except Ex ...

  5. 第一个Maven工程的目录结构和文件内容及联网问题

    [第一个Maven工程] ①目录结构 Hello |---src |---|---main |---|---|---java |---|---|---resources |---|---test |- ...

  6. node.js 利用流实现读写同步,边读边写

    //10个数 10个字节,每次读4b,写1b let fs=require("fs"); function pipe(source,target) { //先创建可读流,再创建可写 ...

  7. Linux下汇编语言学习笔记76 ---

    这是17年暑假学习Linux汇编语言的笔记记录,参考书目为清华大学出版社 Jeff Duntemann著 梁晓辉译<汇编语言基于Linux环境>的书,喜欢看原版书的同学可以看<Ass ...

  8. jd-eclipse插件的安装

    一,资源 jd-eclipse-site-1.0.0-RC2.zip    百度网盘链接:https://pan.baidu.com/s/1GTFFY_1jg4k9vjZNE4JliQ       提 ...

  9. Tomcat配置文件server.xml(转)

    前言 Tomcat隶属于Apache基金会,是开源的轻量级Web应用服务器,使用非常广泛.server.xml是Tomcat中最重要的配置文件,server.xml的每一个元素都对应了Tomcat中的 ...

  10. linux 设置root可以远程登陆

    编辑/etc/ssh/sshd_config 设置 PermitRootLogin yes 重启ssh 服务 ubuntu service ssh start