luoguP4778 Counting swaps
题解
首先,对于每个\(i\)向\(a[i]\)连边.
这样会连出许多独立的环.
可以证明,交换操作不会跨越环.
每个环内的点到最终状态最少交换步数是 \(环的大小-1\)
那么设\(f[i]\)表示环大小为\(i\)的方案数
则
\]
其中
\]
打标可以发现\(f[n] = n^{n-2}(n≠1)\)
那么假设有\(k\)个环,第\(i\)个环大小为\(a[i]\)
则
\]
\(T\)是把\(n-k\)步分进每个环的方案数
\(T=\frac{(n-k)!}{\prod(a[i]-1)!}\)
还有另一种方法算\(T\)(具体看代码)
Code
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10, Mod = 1e9 + 9;
int fpow(int a, int b) {
if (b <= 0) return 1;
int res = 1;
for (; b; b >>= 1, a = 1ll * a * a % Mod) if (b & 1) res = 1ll * res * a % Mod;
return res;
}
bool vis[N];
int to[N], a[N];
int dfs(int x) {
vis[x] = 1;
if (vis[to[x]]) return 1;
else return 1 + dfs(to[x]);
}
int fac[N], ifac[N];
int C(int n, int m) {
if (n < m) return 0;
return 1ll * fac[n] * ifac[n - m] % Mod * ifac[m] % Mod;
}
void solve() {
int n, ans = 1;
scanf("%d", &n);
for (int i = 1; i <= n; i++) scanf("%d", &to[i]);
memset(vis, 0, sizeof(vis));
int len = 0;
for (int i = 1; i <= n; i++)
if (!vis[i])
a[++len] = dfs(i);
// for (int i = 1; i <= len; i++) ans = 1ll * ans * fpow(a[i], a[i] - 2) % Mod * ifac[a[i] - 1] % Mod;
for (int i = 1, sum = 0; i <= len; sum += a[i++] - 1)
ans = 1ll * ans * fpow(a[i], a[i] - 2) % Mod * C(n - sum - len, a[i] - 1) % Mod;
printf("%d\n", /*1ll * ans * fac[n - len] % Mod*/ans);
return ;
}
int main() {
int T;
scanf("%d", &T);
fac[0] = 1;
for (int i = 1; i <= 100000; i++) fac[i] = 1ll * fac[i - 1] * i % Mod;
ifac[100000] = fpow(fac[100000], Mod - 2);
for (int i = 100000; i >= 1; i--) ifac[i - 1] = 1ll * ifac[i] * i % Mod;
while (T--) solve();
return 0;
}
luoguP4778 Counting swaps的更多相关文章
- CH3602 Counting Swaps
题意 3602 Counting Swaps 0x30「数学知识」例题 背景 https://ipsc.ksp.sk/2016/real/problems/c.html Just like yeste ...
- Counting swaps
Counting swaps 给你一个1-n的排列,问用最少的交换次数使之变为递增排列的方案数\(mod\ 10^9+7\),1 ≤ n ≤ 10^5. 解 显然最少的交换次数不定,还得需要找到最小交 ...
- 洛谷P4778 Counting swaps 数论
正解:数论 解题报告: 传送门! 首先考虑最终的状态是固定的,所以可以知道初始状态的每个数要去哪个地方,就可以考虑给每个数$a$连一条边,指向一个数$b$,表示$a$最后要移至$b$所在的位置 显然每 ...
- luogu P4778 Counting swaps
计数套路题?但是我连套路都不会,,, 拿到这道题我一脸蒙彼,,,感谢@poorpool 大佬的博客的指点 先将第\(i\)位上的数字\(p_i\)向\(i\)连无向边,然后构成了一个有若干环组成的无向 ...
- LFYZOJ 104 Counting Swaps
题解 #include <iostream> #include <cstdio> #include <algorithm> #include <cmath&g ...
- lfyzoj104 Counting Swaps
问题描述 给定你一个 \(1 \sim n\) 的排列 \(\{p_i\}\),可进行若干次操作,每次选择两个整数 \(x,y\),交换 \(p_x,p_y\). 请你告诉穰子,用最少的操作次数将给定 ...
- P4778 Counting Swaps 题解
第一道 A 掉的严格意义上的组合计数题,特来纪念一发. 第一次真正接触到这种类型的题,给人感觉好像思维得很发散才行-- 对于一个排列 \(p_1,p_2,\dots,p_n\),对于每个 \(i\) ...
- 0x36 组合计数
组合计算的性质: C(n,m)= m! / (n!(m-n)!) C(n,m)=C(m-n,m); C(n,m)=C(n,m-1)+C(n-1,m-1); 二项式定理:(a+b)^n=sigema(k ...
- 萌新笔记——Cardinality Estimation算法学习(二)(Linear Counting算法、最大似然估计(MLE))
在上篇,我了解了基数的基本概念,现在进入Linear Counting算法的学习. 理解颇浅,还请大神指点! http://blog.codinglabs.org/articles/algorithm ...
随机推荐
- jenkins 打安卓包 cpu使用过高处理操作
登录两个控制台 打包开始后 在其中一台机器执行ps -ef |grep jenkins 找到执行打包的主进程复制pid 在另一个终端上执行 top -H -p pid 将最耗cpu的线程id转换为16 ...
- Windows 10 下 Linux 子系统的安装和使用
介绍 适用于 Windows 的 Linux 子系统(英语:Windows Subsystem for Linux,简称 WSL)是一个为在 Windows 10 和 Windows Server 2 ...
- Asp.Net Core 轻松学系列-4玩转配置文件
目录 前言 另类方式使用 hosting.json 使程序运行于多个端口 结语 前言 在 .NET Core 项目中,配置文件有着举足轻重的地位:与.NetFramework 不同的是,.NE ...
- JS基础_this补充
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- 封装jquery的ajax
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- Vscode ftp
sftp的插件,作者是liximomo 安装插件: 在Vscode的商店中搜索sftp扩展 配置: 一般在开发项目时,总是有多个项目在同时开发.如果要为单一的项目配置的话,就需要打开此项目,快捷键ct ...
- leetcode-62. Unique Paths · DP + vector
题面 A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below). ...
- asp.net mvc 防止跨站攻击
View @using (Html.BeginForm("Contact","Home",FormMethod.Post)) { @Html.AntiForge ...
- GNS3
什么是GNS? GNS Graphical Network Simulator Simulator or Emulator? 尽管GNS全拼包含simulator,但实际上是emulator.我们说其 ...
- jquery.js:9600 POST http://127.0.0.1:8000/news/1/comments/ 500 (Internal Server Error)
什么情况? 代码报错了....查询 语句错误 看 编译提示. 数据 查询 语句的问题!!!!