【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_ ...
随机推荐
- Python 发送企业微信消息
1.获取企业微信信息 1)我的企业 --> 企业信息 --> 企业ID 2)创建一个应用,记录该应用的 AgentId.Secret 2.python代码 #!/usr/bin/env p ...
- js 宏任务和微任务
.宏任务(macrotask )和微任务(microtask ) macrotask 和 microtask 表示异步任务的两种分类. 在挂起任务时,JS 引擎会将所有任务按照类别分到这两个队列中,首 ...
- IScroll在某些win10版本下的奇怪问题
客户的电脑环境: win10版本 企业微信: useragent mozilla/5.0 (windows nt 6.2; wow64) applewebkit/537.36 (khtml, like ...
- THUSC2019去不了记
因为泥萌都去SC了,就我在学校里考水考模拟,所以这就变成了水考模拟游记了 Day1 早上本来要到教室早读,发现教室被由年级前\(100\)的非竞赛生的dalao给占据了,发现聪聪在里面,于是进去愉快的 ...
- 『快乐链覆盖 树形dp』
快乐链覆盖 Description 给定一棵 n 个点的树,你需要找至多 k 条互不相交的路径,使得它们的长度之和最大 定义两条路径是相交的:当且仅当存在至少一个点,使得这个点在两条路径中都出现 定义 ...
- 图解微信小程序---scroll_view实现首页排行榜布局
图解微信小程序---scroll_view实现首页排行榜布局 什么是scroll-view? 滚动视图可滚动视图区域.使用竖向滚动时,需要给scroll-view一个固定高度,通过 WXSS 设置 h ...
- Win10 CompatTelRunner.exe占用磁盘高的解决办法
(1)在运行里输入 taskschd.msc, 打开windows计划任务 (2)参考下图在Application Experience下,1,2,3,4步骤,把所有带有 “CompatTelRun ...
- Dapper学习(三)之其他用法
这里说的其他用法,是指 Async,Buffered,Transaction,Stored Procedure. 1. 首先 dapper支持异步 ExecuteAsync, QueryAsync, ...
- Python基础9
Anacanda软件内更新的方法,而不是每次重装整个软件, 整体更新,省时省力. 但仍要掌握单个包更新的方法.
- laravel框架之状态更改
//表单@if($v['sex']==0) <td class="se" ss="{{$v['sex']}}" id="{{$v['id']}} ...