BZOJ 1129 exgcd+CRT+线段树
思路:
先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+线段树的更多相关文章
- Bzoj 2752 高速公路 (期望,线段树)
Bzoj 2752 高速公路 (期望,线段树) 题目链接 这道题显然求边,因为题目是一条链,所以直接采用把边编上号.看成序列即可 \(1\)与\(2\)号点的边连得是. 编号为\(1\)的点.查询的时 ...
- BZOJ.3938.Robot(李超线段树)
BZOJ UOJ 以时间\(t\)为横坐标,位置\(p\)为纵坐标建坐标系,那每个机器人就是一条\(0\sim INF\)的折线. 用李超线段树维护最大最小值.对于折线分成若干条线段依次插入即可. 最 ...
- BZOJ.1558.[JSOI2009]等差数列(线段树 差分)
BZOJ 洛谷 首先可以把原序列\(A_i\)转化成差分序列\(B_i\)去做. 这样对于区间加一个等差数列\((l,r,a_0,d)\),就可以转化为\(B_{l-1}\)+=\(a_0\),\(B ...
- BZOJ 3779: 重组病毒(线段树+lct+树剖)
题面 escription 黑客们通过对已有的病毒反编译,将许多不同的病毒重组,并重新编译出了新型的重组病毒.这种病毒的繁殖和变异能力极强.为了阻止这种病毒传播,某安全机构策划了一次实验,来研究这种病 ...
- BZOJ 3123 森林(函数式线段树)
题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=3123 题意: 思路:总的来说,查询区间第K小利用函数式线段树的减法操作.对于两棵树的合并 ...
- BZOJ 2124等差子序列 线段树&&hash
[题目描述 Description] 给一个 1 到 N 的排列{Ai},询问是否存在 1<=p1<p2<p3<p4<p5<…<pLen<=N(Len& ...
- Bzoj 3747: [POI2015]Kinoman 线段树
3747: [POI2015]Kinoman Time Limit: 60 Sec Memory Limit: 128 MBSubmit: 553 Solved: 222[Submit][Stat ...
- BZOJ 3155: Preprefix sum( 线段树 )
刷刷水题... 前缀和的前缀和...显然树状数组可以写...然而我不会, 只能写线段树了 把改变成加, 然后线段树维护前缀和, 某点p加, 会影响前缀和pre(x)(p≤x≤n), 对[p, n]这段 ...
- bzoj 1307/1318 玩具 线段树+记录时间戳
玩具 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 743 Solved: 404[Submit][Status][Discuss] Descrip ...
随机推荐
- (五)python3 整型int
int() Python 内置函数,用于将一个字符串或数字转换为整型. int(x, base=10)#以十进制转换x为整型(默认) >>>int() # 不传入参数时,得到结果0 ...
- swing之单选框和复选框
import java.awt.Container; import java.awt.GridLayout; import javax.swing.*; public class num_1v ext ...
- Python介绍以及Python 优缺点
Python是先编译成字节码,然后在解释执行的一门语言,而不是单纯的解释型语言 Python应用场景: Web应用开发. 操作系统管理,服务器运维的自动化脚本, 网络爬虫 科学计算 桌面软件 游戏 服 ...
- 手动模拟一个类似jquery的ajax请求
var $ = { parms:function(obj){ var str = ''; for(var k in obj){ str +=k+'='+obj[k]+'&'; } str = ...
- PAT 1123 Is It a Complete AVL Tree
An AVL tree is a self-balancing binary search tree. In an AVL tree, the heights of the two child sub ...
- node-sass 安装失败
安装 npm install 时偶尔遇到报错:没有安装python或node-sass 安装失败的问题,百度之后发现是被墙了,但根据百度的方法换了淘宝镜像和用了vpn都安装失败, 原因可能是没有卸载之 ...
- 【02】json语法
[02] JSON 语法是 JavaScript 语法的子集. JSON 语法规则 JSON 语法是 JavaScript 对象表示法语法的子集. 数据在名称/值对中 数据由逗号分隔 花括号保存对象 ...
- python爬取数据保存到Excel中
# -*- conding:utf-8 -*- # 1.两页的内容 # 2.抓取每页title和URL # 3.根据title创建文件,发送URL请求,提取数据 import requests fro ...
- java 源码分析1 -String
1. String的本质是一个 char数组,实现了CharSequence 接口, /** The value is used for character storage. */ private f ...
- Ubuntu源码下载方法
首先进入: http://cdimage.ubuntu.com/releases/ 选择相应的版本: 进入release页面: http://cdimage.ubuntu.com/releases/1 ...