BZOJ1129 : [POI2008]Per
枚举LCP,假设前$i-1$个都相同。
那么后面$n-i$个数可以随意排列,第$i$个位置可以填的方案数为后面小于$a_i$的数字个数,树状数组维护。
同时为了保证本质不同,方案数需要除以每个数字的个数的阶乘。
将$m$分解质因数,然后CRT合并即可。
可以先用树状数组处理出所有贡献。
同时在分开计算答案的时候,除了某个超过$\sqrt{m}$的大因子之外,其它模数的逆元都可以线性预处理。
所以总时间复杂度为$O(n\log n)$。
#include<cstdio>
#include<algorithm>
#define N 300010
typedef long long ll;
int n,m,i,a[N],b[N],c[N],bit[N],f[N],g[N],ans,flag,K;ll B,P,x,y,inv[N];
inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
inline int lower(int x){
int l=1,r=n,mid,t;
while(l<=r)if(b[mid=(l+r)>>1]<=x)l=(t=mid)+1;else r=mid-1;
return t;
}
ll exgcd(ll a,ll b){
if(!b)return x=1,y=0,a;
ll d=exgcd(b,a%b),t=x;
return x=y,y=t-a/b*y,d;
}
inline ll rev(ll a){
if(flag&&a<P)return inv[a];
exgcd(a,P);
return (x+P)%P;
}
inline void add(int x,int y){for(;x<=n;x+=x&-x)bit[x]+=y;}
inline int ask(int x){int t=0;for(;x;x-=x&-x)t+=bit[x];return t;}
struct Num{
ll a,b;
Num(){a=1,b=0;}
Num(ll _a,ll _b){a=_a,b=_b;}
Num operator*(const Num&x){return Num(a*x.a%P,b+x.b);}
Num operator/(const Num&x){return Num(a*rev(x.a)%P,b-x.b);}
ll val(){
if(!a||b>=K)return 0;
ll t=a,x=B,k=b;
for(;k;k>>=1,x=x*x%P)if(k&1)t=t*x%P;
return t;
}
void set(ll n){
a=n,b=0;
while(a%B==0)a/=B,b++;
a%=P;
}
}w[N],t;
void solve(ll _B,ll _P,int _K){
B=_B,P=_P,K=_K;
if(P<=n){
flag=1;
for(inv[0]=inv[1]=1,i=2;i<P;i++)inv[i]=(P-inv[P%i])*(P/i)%P;
}else flag=0;
ll tmp=1LL*(m/P)*rev(m/P)%m;
int i;
for(w[0].set(i=1);i<=n;i++)w[i].set(i);
for(i=1;i<=n;i++)w[i]=w[i]*w[i-1];
for(i=1;i<=n;i++)c[i]=0;
for(i=1;i<=n;i++)c[a[i]]++;
Num all(1,0);
for(i=1;i<=n;i++)all=all*w[c[i]];
for(i=1;i<=n;i++){
if(g[i])t.set(g[i]),f[i]=(tmp*(t*w[n-i]/all).val()+f[i])%m;
c[a[i]]--;
all=all/w[c[a[i]]+1]*w[c[a[i]]];
}
}
void divide(int n){
int i=1;
for(int i=2;i*i<=n;i++)if(n%i==0){
int x=1,k=0;
while(n%i==0)n/=i,x*=i,k++;
solve(i,x,k);
}
if(n>1)solve(n,n,1);
}
int main(){
read(n),read(m);
for(i=1;i<=n;i++)read(a[i]),b[i]=a[i];
std::sort(b+1,b+n+1);
for(i=1;i<=n;i++)a[i]=lower(a[i]);
for(i=1;i<=n;i++)c[a[i]]++;
for(i=1;i<=n;i++)add(i,c[i]);
for(i=1;i<=n;i++)g[i]=ask(a[i]-1),add(a[i],-1);
divide(m);
for(ans=i=1;i<=n;i++)ans=(ans+f[i])%m;
return printf("%d",ans),0;
}
BZOJ1129 : [POI2008]Per的更多相关文章
- [BZOJ1112][POI2008]砖块Klo
[BZOJ1112][POI2008]砖块Klo 试题描述 N柱砖,希望有连续K柱的高度是一样的. 你可以选择以下两个动作 1:从某柱砖的顶端拿一块砖出来,丢掉不要了. 2:从仓库中拿出一块砖,放到另 ...
- [bzoj1122][POI2008]账本BBB
1122: [POI2008]账本BBB Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 402 Solved: 202[Submit][Status ...
- BZOJ 1113: [Poi2008]海报PLA
1113: [Poi2008]海报PLA Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1025 Solved: 679[Submit][Statu ...
- BZOJ 1116: [POI2008]CLO
1116: [POI2008]CLO Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 922 Solved: 514[Submit][Status][ ...
- BZOJ 1112: [POI2008]砖块Klo
1112: [POI2008]砖块Klo Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1736 Solved: 606[Submit][Statu ...
- BZOJ 1124: [POI2008]枪战Maf
1124: [POI2008]枪战Maf Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 617 Solved: 236[Submit][Status ...
- BZOJ 1123: [POI2008]BLO
1123: [POI2008]BLO Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1030 Solved: 440[Submit][Status] ...
- BZOJ 1121: [POI2008]激光发射器SZK
1121: [POI2008]激光发射器SZK Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 792 Solved: 653[Submit][Sta ...
- BZOJ1132: [POI2008]Tro
1132: [POI2008]Tro Time Limit: 20 Sec Memory Limit: 162 MBSubmit: 815 Solved: 211[Submit][Status] ...
随机推荐
- ionic的常用命令总结以及正式发布的准备
常用命令: npm install -g ionic cordova(需要安装node) ionic start cutePuppyPics --v2(建app cutePuppyPics app名字 ...
- Https方式使用Git@OSC设置密码的方式
Https方式使用Git@OSC设置密码的方式 62561_silentboy Zoker3 years ago member https方式每次都要输入密码,按照如下设置即可输入一次就不用再手输入密 ...
- JDBC之存储过程
存储过程的语法创建就不说了,这里这篇博客 就挺详细了http://blog.sina.com.cn/s/blog_52d20fbf0100ofd5.html. 1. Java代码调用没有参数的存错过程 ...
- webstorm快捷键大全
使用webstorm一段时间了,这里分享一下常用到的快捷键,不用死记,孰能生巧! Ctrl+/ 或 Ctrl+Shift+/ 注释(// 或者/*-*/ ) Shift+F6 重构-重命名 Ctrl+ ...
- 基础的jdbc连接数据库操作
首先我们知道在数据库中,我们可以直接写sql或者直接通过数据库工具操作数据,但是在java程序中我们是不能直接操作数据库数据的,所以这就引入了jdbc操作. 百度百科:JDBC(Java Data B ...
- Ubuntu14.04更新源、安装chrome/搜狗输入法
目录: 1.更新源 2.安装chrome 3.安装搜狗输入法 1.更新源 三步: cp /etc/apt/sources.list /etc/apt/sources.list_backup ...
- Activity系列讲解---数据传递
在Android中,不同的Activity实例可能运行在一个进程中,也可能运行在不同的进程中.因此需要一种特别的机制帮助我们在Activity之间传递消息.Android中通过Intent对象来表示一 ...
- (转帖)开源容器集群管理系统Kubernetes架构及组件介绍
最近在搞Docker还有她的管理工具,选型Kuberetes后,被她的术语和概念搞得晕头转向...看了一篇文章还不错,放到这里分享出来. 地址:http://www.linuxidc.com/Linu ...
- 排序之----插入排序(C#实现)
算法步骤:(从小到大) 1:将第一个元素与第二个元素比较大小,如果第一个元素小于等于第二个元素,不做处理,继续比较第二个元素和第三个元素. 如果第三个元素小于第二个元素,保存要移动的元素(第三个元素) ...
- 通过挂载系统光盘搭建本地yum仓库的方法
在CentOS系统中,我们常常会安装大量的软件,但许多软件包都存在需要依赖性,当然我们可以通过一一安装依赖包来完成安装,但对于有些软件包需要大量的依赖包,再一一安装起来会显得特别麻烦.接下来我们就来讲 ...