当前位置: 首页 > news >正文

深黯Solution

先对于 \(n=4\) 打表所有的排列,然后观察规律。

考虑经典套路拆逆序对贡献为每一位的分别贡献。(后面比它小的数)

给个贡献的表感受一下(左边排列右边贡献):

1 2 3 4|0 0 0 0
1 2 4 3|0 0 1 0
1 3 2 4|0 1 0 0
1 3 4 2|0 1 1 0
1 4 2 3|0 2 0 0
1 4 3 2|0 2 1 0
2 1 3 4|1 0 0 0
2 1 4 3|1 0 1 0

然后我们发现对于第 \(i\) 位的贡献的 “循环节” 是一个下限为 \(0\),上限为 \(n-i\),公差为 \(1\) 的等差数列但是每个数字会重复 \((n-i)!\) 次。

还有更神奇的事情,当 \(i+1\) 的贡献循环一次时,\(i\) 的贡献加一!

于是考虑将原数组 \(a\) 的逆序对用树状数组/线段树处理后从右向左考虑贡献,记录 \(i+1\) 位的第一次为 \(0\) 的地方,对于最前边和最后面不是 “循环节” 的地方暴力加答案,“循环节” 直接用等差数列求即可。

复杂度上,对于 \((n-i)>20\)\(i\),贡献最多会改变一次(\(20!>10^{18}\)),因此复杂度为 \(O(n\log n+20^2)\)

#include<bits/stdc++.h>
#define int __int128
using namespace std;
namespace kong{bool st;}
namespace zhu{
struct{int l,r,sum,lazy;
}tr[2002000];
#define ls (id<<1)
#define rs (id<<1|1)
#define l(x) tr[x].l
#define r(x) tr[x].r
#define sm(x) tr[x].sum
#define lz(x) tr[x].lazy
#define mid ((l(id)+r(id))>>1)
#define up sm(id)=sm(ls)+sm(rs)
#define dw\sm(ls)+=lz(id)*(r(ls)-l(ls)+1);\sm(rs)+=lz(id)*(r(rs)-l(rs)+1);\lz(ls)+=lz(id);\lz(rs)+=lz(id);\lz(id)=0;
void build(int id,int l,int r){l(id)=l,r(id)=r;if(l==r) return;build(ls,l,mid);build(rs,mid+1,r);
}
void add(int id,int l,int r,int y){if(l(id)>=l&&r(id)<=r){sm(id)+=(r(id)-l(id)+1)*y;lz(id)+=y;return;}dw;if(l<=mid){add(ls,l,r,y);}if(r>mid){add(rs,l,r,y);}up;
}
int que(int id,int x){if(l(id)==r(id)){return sm(id);}dw;if(x<=mid){return que(ls,x);}else{return que(rs,x);}
}
#undef sm
int n,a[500500],k,mod,sum[30],st[500500];
int sm(int x){if(x<=20) return sum[x];else return 2e18;
}
string main(){freopen("army.in","r",stdin);freopen("army.out","w",stdout); long long t1,t2,t3;cin>>t1>>t2>>t3;n=t1,k=t2,mod=t3;sum[0]=1;for(int i=1;i<=20;i++){sum[i]=sum[i-1]*i;}for(int i=1;i<=n;i++){cin>>t1;a[i]=t1;}build(1,1,n);for(int i=n;i>=1;i--){st[i]=que(1,a[i]);add(1,a[i]+1,n,1);}int lstbh=1,ans=0;for(int i=n-1;i>=1;i--){if(!lstbh){ans=(ans+k*st[i]%mod)%mod;continue;}int t=k,now=st[i]+1,mx=n-i,j=lstbh,twc=sm(n-i);
//		cout<<"---------\n";
//		cout<<i<<'\n';
//		cout<<st[i]<<' '<<mx<<' '<<lstbh<<'\n';ans=(ans+lstbh*st[i]%mod)%mod;t-=lstbh;
//		cout<<"初始    :"<<ans<<" "<<t<<'\n';while(now<=mx&&t>=twc){j+=twc;t-=twc;ans=(ans+twc*now%mod)%mod;now++;}
//		cout<<"前端杂碎:"<<ans<<" "<<t<<'\n';if(now<=mx){lstbh=0;ans=(ans+t*now%mod)%mod;
//			cout<<"死";continue;}lstbh=j;int xhc=sm(n-i+1);ans=(ans+(t/xhc)*twc%mod*((0+mx)*(mx+1)/2%mod)%mod)%mod;t=t%xhc;
//		cout<<"循环    :"<<ans<<" "<<t<<'\n';now=0;while(t>=twc){t-=twc;ans=(ans+twc*now%mod)%mod;now++;}ans=(ans+t*now%mod)%mod;
//		cout<<"尾端杂碎:"<<ans<<" "<<t<<'\n';}long long out=(ans%mod+mod)%mod;cout<<out<<'\n';return "last";
}
}
namespace kong{bool ed;double MB(){return (&st-&ed)/1048576.0;}}
signed main(){cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);cerr<<zhu::main()<<'\n'<<kong::MB()<<'\n';
}
/*
5 9 1000000007
5 2 4 3 1 */
http://www.sczhlp.com/news/12537/

相关文章:

  • Azkaban启用常见问题说明(启动报错)
  • 接入提供方的AI
  • 使用 MetaWeblog API 修改博客
  • Poste.io自建域名的邮箱本地化部署方案 - 明明就
  • vscode里退出github Copilot账号,切换github Copilot账号,completion quota用完了,显示100%,vscode不能自动补全
  • Grain用于读取和处理用于训练和评估 JAX 模型的数据
  • 华三-OSPF
  • 嘉立创地阔星STM32F103C8T6 arduino ch340串口烧录
  • 实战指南|电力管理系统搭建全流程解析
  • 公司项目之 qiankun 微前端项目 总结;
  • 《ESP32-S3使用指南—IDF版 V1.6》第三十三章 RGB显示屏实验
  • Python工具箱系列(六十五)
  • 华三-堆叠
  • 赋能 Gulp 构建流:使用腾讯云 EdgeOne 为 Pug 博客注入全球 CDN 与安全防护能力
  • redis主从复制详解
  • 使用XXL-SSO实现登录认证以及权限管控
  • XXL-SSO v2.0.0 发布|单点登录框架
  • XXL-TOOL v2.0.0 发布 | Java工具类库
  • Python工具箱系列(六十一)
  • Python工具箱系列(六十)
  • LeNet(Jax/Flax)实现
  • CMC蒲和平1.2
  • 华三-无线-集中转发
  • CVPR 2024计算机视觉前沿论文速览
  • 华三-无线-本地转发
  • mainwindows.cpp
  • 华三-BFD
  • 华三-路由策略
  • 华三-策略路由
  • 华三-浮动路由