第一道 A 掉的严格意义上的组合计数题,特来纪念一发。

第一次真正接触到这种类型的题,给人感觉好像思维得很发散才行……


对于一个排列 \(p_1,p_2,\dots,p_n\),对于每个 \(i\) 向 \(p_i\) 连一条边,可以发现整个构成了一个由若干环组成的图,目标是将这些环变为自环。

引理:把长度为 \(n\) 的环变为 \(n\) 个自环,最少交换次数为 \(n-1\)。

用归纳法证,对于当前情况,任意一次交换都将其拆为两个环,由淘汰赛法则可知引理成立。

记 \(F_n\) 表示在最少交换次数下把长度为 \(n\) 的环变为 \(n\) 个自环,有多少种交换方式。由前所述,我们每次都将其拆为两个环,不妨设两个环长度为 \(x,y\),并记 \(T(x,y)\) 表示有多少种方法可将一个长度为 \(n\) 的环变为长度为 \(x,y\) 的两个环,那么当 \(n\) 为偶数且 \(x=y\) 时有 \(T(x,y)=\frac{n}{2}\),其他情况 \(T(x,y)=n\)。由于 \(x\) 环与 \(y\) 环的操作互不干扰,两边的操作可以随意排列,因此这里就是一个多重集的全排列。

于是有了递归表达式: $$F_n=\sum_{x+y=n}\left(T(x,y)F_xF_y\frac{(n-2)!}{(x-1)!(y-1)!}\right)$$ 对于题目中的所有 \(k\) 个环,记它们的长度为 \(\{l_k\}\),最终答案为:

\[\prod^{k}_{i=1}F_{l_{i}}\dfrac{(n-k)!}{\prod^{k}_{i=1}(l_i-1)!}
\]

还没完,经过JOJO的洗礼之后发现 \(F_n=n^{n-2}\)!复杂度立马降为 \(O(n\log n)\)……

(找环这个骚操作是照题解区 dalao 学的,只能 orz

#include <bits/stdc++.h>
using namespace std;
typedef long long ll; const int N=1e5+5;
const ll mod=1e9+9;
int n,a[N],L[N],cnt;
ll fac[N]={1,1},F[N]={0,1};
bool vis[N]; ll qpow(ll bas,ll p)
{
ll res=1; bas%=mod;
for(;p;p>>=1)
{
if(p&1) res=res*bas%mod;
bas=bas*bas%mod;
}
return res;
} int dfs(int x)
{
vis[x]=1;
if(vis[a[x]]) return 1;
return dfs(a[x])+1;
} int main()
{
int T; scanf("%d",&T);
for(int i=2;i<N;++i)
fac[i]=i*fac[i-1]%mod,
F[i]=qpow(i,i-2)%mod;
while(T--)
{
memset(vis,0,sizeof(vis));
cnt=0;
scanf("%d",&n);
for(int i=1;i<=n;++i)
scanf("%d",&a[i]);
for(int i=1;i<=n;++i)
if(!vis[i]) L[++cnt]=dfs(i);
ll ans=fac[n-cnt];
for(int i=1;i<=cnt;++i)
ans=ans*F[L[i]]%mod*qpow(fac[L[i]-1],mod-2)%mod;
printf("%lld\n",ans);
}
return 0;
}

P4778 Counting Swaps 题解的更多相关文章

  1. 洛谷P4778 Counting swaps 数论

    正解:数论 解题报告: 传送门! 首先考虑最终的状态是固定的,所以可以知道初始状态的每个数要去哪个地方,就可以考虑给每个数$a$连一条边,指向一个数$b$,表示$a$最后要移至$b$所在的位置 显然每 ...

  2. luogu P4778 Counting swaps

    计数套路题?但是我连套路都不会,,, 拿到这道题我一脸蒙彼,,,感谢@poorpool 大佬的博客的指点 先将第\(i\)位上的数字\(p_i\)向\(i\)连无向边,然后构成了一个有若干环组成的无向 ...

  3. CH3602 Counting Swaps

    题意 3602 Counting Swaps 0x30「数学知识」例题 背景 https://ipsc.ksp.sk/2016/real/problems/c.html Just like yeste ...

  4. Counting swaps

    Counting swaps 给你一个1-n的排列,问用最少的交换次数使之变为递增排列的方案数\(mod\ 10^9+7\),1 ≤ n ≤ 10^5. 解 显然最少的交换次数不定,还得需要找到最小交 ...

  5. 【SP26073】DIVCNT1 - Counting Divisors 题解

    题目描述 定义 \(d(n)\) 为 \(n\) 的正因数的个数,比如 \(d(2) = 2, d(6) = 4\). 令 $ S_1(n) = \sum_{i=1}^n d(i) $ 给定 \(n\ ...

  6. LFYZOJ 104 Counting Swaps

    题解 #include <iostream> #include <cstdio> #include <algorithm> #include <cmath&g ...

  7. lfyzoj104 Counting Swaps

    问题描述 给定你一个 \(1 \sim n\) 的排列 \(\{p_i\}\),可进行若干次操作,每次选择两个整数 \(x,y\),交换 \(p_x,p_y\). 请你告诉穰子,用最少的操作次数将给定 ...

  8. luoguP4778 Counting swaps

    题目链接 题解 首先,对于每个\(i\)向\(a[i]\)连边. 这样会连出许多独立的环. 可以证明,交换操作不会跨越环. 每个环内的点到最终状态最少交换步数是 \(环的大小-1\) 那么设\(f[i ...

  9. POJ 2386 Lake Counting 搜索题解

    简单的深度搜索就能够了,看见有人说什么使用并查集,那简直是大算法小用了. 由于能够深搜而不用回溯.故此效率就是O(N*M)了. 技巧就是添加一个标志P,每次搜索到池塘,即有W字母,那么就觉得搜索到一个 ...

随机推荐

  1. 重新整理 mysql 基础篇————— mysql 事务[三]

    前言 简单整理一下事务. 正文 事务有四大特性: 1.原子性(atomicity) 一个事务必须被视为一个不可分割的最小单元. 2.一致性(consistency) 数据库总是从一个一致性的状态转换到 ...

  2. RF中在测试用例集上设置标签

    1.有时候我们在执行测试用例时只想执行部分测试用例集下面的测试用例,这时可以在相应的测试用例集中设置标签,然后运行时选择标签执行对应的测试用例 语法: *** Settings *** Force T ...

  3. C# 扫描并读取图片中的文字

    本文介绍如何通过C# 程序来扫描并读取图片中的文字,这里以创建一个.Net Core程序为例.下面是具体步骤,供参考. 程序测试环境: Visual Studio版本要求不低于2017 图片扫描工具: ...

  4. 在Centos7下安装RabbitMQ

    1.背景 不用多说,这东西好用! 2.安装 步骤一:下载安装包 链接:https://pan.baidu.com/s/1PIYI60wX6L7BtVyVft-vSA 提取码:1234 复制这段内容后打 ...

  5. ES系列(七):多节点任务的分发与收集实现

    我们知道,当我们对es发起search请求或其他操作时,往往都是随机选择一个coordinator发起请求.而这请求,可能是该节点能处理,也可能是该节点不能处理的,也可能是需要多节点共同处理的,可以说 ...

  6. 聊聊 Feign 的实现原理

    What is Feign? Feign 是⼀个 HTTP 请求的轻量级客户端框架.通过 接口 + 注解的方式发起 HTTP 请求调用,面向接口编程,而不是像 Java 中通过封装 HTTP 请求报文 ...

  7. 旋转的球(animation与 transform)

    <html> <head> <meta http-equiv="Content-Type" content="text/html; char ...

  8. 单元测试布道二:在全新的 DDD 架构上进行单元测试

    目录 回顾 dotnet 单元测试相关的工具和知识 可测试性 不确定性/未决行为 依赖于实现:不可 mock 复杂继承/高耦合代码:测试困难 实战:在全新的 DDD 架构上进行单元测试 需求-迭代1: ...

  9. Task异常捕获的方式

    这节来讲一下如果捕获Task的异常. 当Task运行中出现了异常,正常情况下我们在主线程的Try是捕获不到的,而如果在Task内部写try,出现了异常我们会完全不知道.下面就来介绍几个主线程捕获Tas ...

  10. ES6学习笔记之函数(二)

    5.作用域 使用默认参数时,参数会形成一个独立的作用域,此作用域与函数体中的作用域是平行关系,互不影响. var x = 1; function show(x, y= function () { x= ...