【JZOJ100207】【20190705】决心
题目
你需要构造一个排列
初始时\(p_i=i\),一次操作定义为:
选择一些\((x_i,y_i)\),满足每个数字只能出现一次
依次交换\(p_{x_i},p_{y_i}\)
定义一个排列 \(P\) 的最少交换次数为\(f(P)\)
现在 \(P\) 有 \(k\) 个位置的排列顺序是未知的,定义某一种确定顺序的方案是\(P'\)
求\(\sum f(P')\)
\(1 \le n \le 10^6 \ , \ k \le min(12,n)\)
题解
首先操作次数不会超过2,考虑每一个轮换
.png)
.png)
考虑一个排列\(P\),它的贡献是:
1.如果所有轮换的大小<=2 ,最少的步数为0/1,贡献为02.如果存在轮换的大小>2,最少的步数为2,考虑贡献
大小不同的轮换不会互相影响
大小相同的轮换可以两两拼在一起,也可以单独存在
写成dp即$h_{i,j} \ = \ h_{i,j-1}i + h_{i,j-2}(j-1)i $
如果大小为\(i\)的轮换有\(m_i\)个,总贡献为\(\prod h_{i,m_i}\)
如果确定的点指向不确定的点存在一条链\(l\),那么就把不确定的点的大小看做\(|l|+1\)
预处理出所有的\(h\),这样就可以只考虑不确定的点的排列
由于贡献只和轮换的大小有关,可以枚举集合划分再把贡献乘以一个圆排列
时间复杂度\(O(n \ log \ n + bell(k) \ k)\)
Code
#include<bits/stdc++.h>
#define pb push_back
using namespace std;
const int N=1000010,mod=1e9+7;
int n,k,p[N],q[N],cnt[N],pos[N],a[N],b[N],c[N],bl[N],iv[N],vis[N],T,preans,precnt[N],ans,fac[N],prefg1,prefg2,Bell;
vector<int>h[N];
void inc(int&x,int y){x+=y;if(x>=mod)x-=mod;}
int pw(int x,int y){
int re=1;
for(;y;y>>=1,x=1ll*x*x%mod)
if(y&1)re=1ll*re*x%mod;
return re;
}
void pre(){
for(int i=fac[0]=1;i<=n;++i){
fac[i]=1ll*fac[i-1]*i%mod;
int lim=n/i;
h[i].pb(1);h[i].pb(i);
for(int j=2;j<=lim;++j){
h[i].pb((h[i][j-1]+1ll*h[i][j-2]*(j-1)%mod)*i%mod);
}
}
}
void calc(int tot){
static int st[N],tp;
++T;tp=0;
for(int i=1;i<=tot;++i)b[i]=0,c[i]=0;
for(int i=1;i<=k;++i)b[bl[i]]++,c[bl[i]]+=a[i];
int re=1,fg1=prefg1,fg2=prefg2;
for(int i=1;i<=tot;++i){
re=1ll*re*fac[b[i]-1]%mod;
cnt[c[i]]++;fg1|=c[i]>1;fg2|=c[i]>2;
if(vis[c[i]]!=T)vis[c[i]]=T,st[++tp]=c[i];
}
if(!fg1)re=1;
if(fg2)re=1ll*re*preans%mod;
for(int i=1;i<=tp;++i){
int x=st[i];
if(fg2)re=1ll*re*iv[x]%mod*h[x][cnt[x]]%mod;
cnt[x]=precnt[x];
}
inc(ans,re);
}
void dfs(int x,int y){
if(x==k+1){calc(y);return;}
for(int i=1;i<=y+1;++i){
bl[x]=i;
dfs(x+1,max(i,y));
}
}
int main(){
freopen("determination.in","r",stdin);
freopen("determination.out","w",stdout);
scanf("%d%d",&n,&k);k=0;
for(int i=1;i<=n;++i){
scanf("%d",&p[i]);
if(p[i])q[p[i]]=i;else pos[++k]=i;
}
for(int i=1;i<=k;++i){
int len=1;vis[pos[i]]=1;
for(int j=q[pos[i]];j;j=q[j])vis[j]=1,len++;
a[i]=len;
}
for(int i=1;i<=n;++i)if(!vis[i]){
int len=1;vis[i]=1;
for(int j=p[i];j!=i;j=p[j])vis[j]=1,len++;
cnt[len]++;prefg2|=len>2;prefg1|=len>1;
}
pre();
preans=1;
for(int i=1;i<=n;++i){
precnt[i]=cnt[i];
preans=1ll*preans*h[i][cnt[i]]%mod;
iv[i]=pw(h[i][cnt[i]],mod-2);
vis[i]=0;
}
dfs(1,0);
cout<<ans<<endl;
return 0;
}
【JZOJ100207】【20190705】决心的更多相关文章
- 微软的决心,开发者的信心!惊喜的 Connect(); // 2016
微软的决心,开发者的信心!惊喜的 Connect(); // 2016 Visual Studio for Mac 2014 年 11 月 13 日,微软宣布 .NET 开源与跨平台.两年后的今天 ...
- happy and angry day! 2019-07-05
2019-07-05 01:59:51 现在我是挺开心的哈! 直面困难!迎难而上!毫无畏惧! 现在我的结果,少不了大家给我的支持与鼓励! 鸣谢 章香涛老师---------在各个方面鼓舞了我,激发了我 ...
- _00023 Kafka 奇怪的操作_001它们的定义Encoder达到Class数据传输水平和决心
博文作者:妳那伊抹微笑 博客地址:http://blog.csdn.net/u012185296 博文标题:_00023 Kafka 诡异操作_001自己定义Encoder实现Class级别的数据传送 ...
- 谁的用户在世界上是  明基决心保时捷设计标准
谈到保时捷.相信非常多人都非常了解,世界名车啊,仅仅有高富帅才玩儿得起.只是,假设由保时捷的设计师来设计一款显示器,水准一流.质地厚道,且价格亲民,你怎么看? 如近期京东上热销的明基G ...
- C指针决心 ------ 指针的概念和元素
本文是自己学习所做笔记,欢迎转载,但请注明出处:http://blog.csdn.net/jesson20121020 指针在C语言中的地位,不用多说. 指针的概念 指针是一个特殊的变量,它里面存储 ...
- C指针决心 ------ 指针表达式
本文是自己学习所做笔记.欢迎转载.但请注明出处:http://blog.csdn.net/jesson20121020 所谓的指针表达式是指一个表达式.其结果是一个指针. 例1. int a,b; ...
- OCP-1Z0-051-标题决心-文章2称号
2. View the Exhibit to examine the description for the SALES table. Which views can have all DML ope ...
- C++ 虚函数表决心
C++ 虚函数表解析 xml:namespace prefix = o /> 陈皓 http://blog.csdn.net/haoel 前言 C++中的虚函数的作用主要是实现了多态的机制. 关 ...
- OCP-1Z0-051-标题决心-文章5称号
5. Which SQL statements would display the value 1890.55 as $1,890.55? (Choose three .) A. SELECT TO_ ...
随机推荐
- Vue双向绑定原理(我尽量写的。简洁)
先问自己两个问题: 1.app.message修改数据的时候,Vue内部是如何监听message数据发生改变的 使用Object.defineProperty ->监听对象属性的改变 2.当数据 ...
- spring的15个经典面试题
总结Spring框架的15个经典面试题. 什么是Spring框架? Spring是一种轻量级框架,旨在提高开发人员的开发效率以及系统的可维护性. 我们一般说的Spring框架就是Spring Fram ...
- 基于贝叶斯网(Bayes Netword)图模型的应用实践初探
1. 贝叶斯网理论部分 笔者在另一篇文章中对贝叶斯网的理论部分进行了总结,在本文中,我们重点关注其在具体场景里的应用. 2. 从概率预测问题说起 0x1:条件概率预测模型之困 我们知道,朴素贝叶斯分类 ...
- iTextSharp生成pdf含模板(一)---制作pdf模板
参考地址:https://www.cnblogs.com/ibeisha/p/itextsharp-pdf.html 一.使用场景:在线填写一些信息,根据对应的信息生成奖状. 二.解决方案 1.新建w ...
- 使用Alipay代码源,构建自己的Docker镜像
1. alipay 镜像仓库 地址 (自行换成自己的阿里镜像云DockerHub地址) https://cr.console.aliyun.com/repository/ 2.alipay 代码云 地 ...
- 项目中使用Redis的游标scan的一些小问题
最近项目中有一个需求就是在下拉中要筛选车辆列表,本来想着是在内存中全部用程序去遍历处理,但发现数据有点多,一个个去处理会有点慢.然后就找到了redis的游标 感觉这个能满足我的需求,我可以把key存成 ...
- k8s时区问题解决方案
前几天在使用k8s中的CronJob时发现了一个很奇怪的问题, 按照官方文档的demo跑起来是没有任何问题的, 但是当我想要设置每天一个固定时间点例如12点20执行一个job的时候,到了时间之后无论如 ...
- python基础知识(最基本)
保留字(关键字) False None True and as break class continue def elif else except finally for from global ...
- 简洁的 systemd 操作指南Linux下Service文件服务说明(转)
1.服务权限systemd有系统和用户区分:系统(/user/lib/systemd/system/).用户(/etc/lib/systemd/user/). 一般系统管理员手工创建的单元文件建议存放 ...
- 类型转换 String——》Char OR Char ——》String
String转换为char 在Java中将String转换为char是非常简单的.1. 使用String.charAt(index)(返回值为char)可以得到String中某一指定位置的char.2 ...