【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,考虑每一个轮换
考虑一个排列\(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_ ...
随机推荐
- Python - 批量下载 IIS 共享的文件
1.说明 用 IIS 以WEB形式发布了本地文件夹,提供文件下载,并设置了访问权限:默认下载需要点击一个一个的下载,web界面如下: 3.脚本 执行脚本批量下载文件,会在当前目录创建文件夹,并压缩该文 ...
- ucore实验Lab1知识点总结
Intel 80386 ucore目前支持的硬件环境是基于Intel 80386以上的计算机系统. Intel 80386是80x86系列中的第一种32位微处理器.80386的内部和外部数据总线都是3 ...
- HTML+css基础 三大列表
三大列表: 1.无序列表 ul 标签属性type 决定项目符号的类型 disc(实心圆)square (方形) circle 空心圆 里面的子标签是li 2.有序列表 ol t ...
- 关于预装操作系统的ThinkPad的分区建议
Think的个人电脑产品大部分预装有正版操作系统,当前新产品出厂时默认都是一个大分区“C”和一个恢复分区“Q”,很多用户都会要求客服人员提供分区服务,在这里我简单说一下关于分区的几点注意事项望各位参考 ...
- 在Mac 上搭建Linux虚拟机--MacOS & VMware10 & CentOS 7
在大型项目开发中, 需要使用Linux下的C语言对工程进行开发, 在个人PC或者工作站上搭建Linux系统十分容易且方便. 本篇文章将介绍操作系统和虚拟机的搭建: 1 操作系统2 虚拟机概念3 Lin ...
- Mysql系列(十二)—— 索引下推优化
索引条件下推(ICP)是对MySQL使用索引从表中检索行的情况的优化.如果没有ICP,存储引擎会遍历索引以查找基表中的行,并将它们返回给MySQL服务器,该服务器会评估WHERE行的条件.启用ICP后 ...
- 关于thinkphp3.2.3集成phpmailer
关于thinkphp3.2.3集成phpmailer 1 我用的是phpmailer5.1的版本 先把文件解压缩放到这个位置 2 封装到函数里面 function email($email,$tit ...
- python接收字符并回显
# -*- coding: utf-8 -* import serial import time # 打开串口 ser = serial.Serial("/dev/ttyAMA0" ...
- Maven学习 一 (下载安装)
Maven简介 Apache Maven 是一个软件项目管理工具.基于项目对象模型(project Object Model ,POM)的概念,Maven可用来管理项目的依赖,编译,文档等信息 使用M ...
- 解决Eclipe安装不上android的ADT的办法
Eclipse,https://dl-ssl.google.com/android/eclipse/安装不上去,ADT在线安装装不了,用离线包又出问题时会不会疯掉. 显然,国内网络和谐掉了google ...