题目链接

题解

首先,对于每个\(i\)向\(a[i]\)连边.

这样会连出许多独立的环.

可以证明,交换操作不会跨越环.

每个环内的点到最终状态最少交换步数是 \(环的大小-1\)

那么设\(f[i]\)表示环大小为\(i\)的方案数

\[f[i] = \sum_{x+y=i}f[x] * f[y] * g(x,y) * (^{i-1}_{x-1})
\]

其中

\[g(x,y)=\{^{\frac{x+y}{2}{(x+y为偶数且x=y)}}_{x+y(else)}
\]

打标可以发现\(f[n] = n^{n-2}(n≠1)\)

那么假设有\(k\)个环,第\(i\)个环大小为\(a[i]\)

\[ans = \prod f[a[i]] *T
\]

\(T\)是把\(n-k\)步分进每个环的方案数

\(T=\frac{(n-k)!}{\prod(a[i]-1)!}\)

还有另一种方法算\(T\)(具体看代码)

Code

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. const int N = 1e5 + 10, Mod = 1e9 + 9;
  4. int fpow(int a, int b) {
  5. if (b <= 0) return 1;
  6. int res = 1;
  7. for (; b; b >>= 1, a = 1ll * a * a % Mod) if (b & 1) res = 1ll * res * a % Mod;
  8. return res;
  9. }
  10. bool vis[N];
  11. int to[N], a[N];
  12. int dfs(int x) {
  13. vis[x] = 1;
  14. if (vis[to[x]]) return 1;
  15. else return 1 + dfs(to[x]);
  16. }
  17. int fac[N], ifac[N];
  18. int C(int n, int m) {
  19. if (n < m) return 0;
  20. return 1ll * fac[n] * ifac[n - m] % Mod * ifac[m] % Mod;
  21. }
  22. void solve() {
  23. int n, ans = 1;
  24. scanf("%d", &n);
  25. for (int i = 1; i <= n; i++) scanf("%d", &to[i]);
  26. memset(vis, 0, sizeof(vis));
  27. int len = 0;
  28. for (int i = 1; i <= n; i++)
  29. if (!vis[i])
  30. a[++len] = dfs(i);
  31. // for (int i = 1; i <= len; i++) ans = 1ll * ans * fpow(a[i], a[i] - 2) % Mod * ifac[a[i] - 1] % Mod;
  32. for (int i = 1, sum = 0; i <= len; sum += a[i++] - 1)
  33. ans = 1ll * ans * fpow(a[i], a[i] - 2) % Mod * C(n - sum - len, a[i] - 1) % Mod;
  34. printf("%d\n", /*1ll * ans * fac[n - len] % Mod*/ans);
  35. return ;
  36. }
  37. int main() {
  38. int T;
  39. scanf("%d", &T);
  40. fac[0] = 1;
  41. for (int i = 1; i <= 100000; i++) fac[i] = 1ll * fac[i - 1] * i % Mod;
  42. ifac[100000] = fpow(fac[100000], Mod - 2);
  43. for (int i = 100000; i >= 1; i--) ifac[i - 1] = 1ll * ifac[i] * i % Mod;
  44. while (T--) solve();
  45. return 0;
  46. }

luoguP4778 Counting swaps的更多相关文章

  1. CH3602 Counting Swaps

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

  2. Counting swaps

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

  3. 洛谷P4778 Counting swaps 数论

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

  4. luogu P4778 Counting swaps

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

  5. LFYZOJ 104 Counting Swaps

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

  6. lfyzoj104 Counting Swaps

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

  7. P4778 Counting Swaps 题解

    第一道 A 掉的严格意义上的组合计数题,特来纪念一发. 第一次真正接触到这种类型的题,给人感觉好像思维得很发散才行-- 对于一个排列 \(p_1,p_2,\dots,p_n\),对于每个 \(i\) ...

  8. 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 ...

  9. 萌新笔记——Cardinality Estimation算法学习(二)(Linear Counting算法、最大似然估计(MLE))

    在上篇,我了解了基数的基本概念,现在进入Linear Counting算法的学习. 理解颇浅,还请大神指点! http://blog.codinglabs.org/articles/algorithm ...

随机推荐

  1. 联想U310 安装系统后无法识别机械硬盘处理

    过程: 原30G的固态更换成250G的 mSATA固态,去掉机械硬盘,开始在固态里安装系统, 系统用PE登录,安装正版Win7 64B 专业版, 安装结束,接上机械硬盘, *PE下,可以正常识别2块硬 ...

  2. java基础知识学习 内存相关

    Java 内存分配策略 静态存储区(方法区):主要存放静态数据.全局 static 数据和常量.这块内存在程序编译时就已经分配好,并且在程序整个运行期间都存在. 栈区 :当方法被执行时,方法体内的局部 ...

  3. ppt调整三级标题的位置

    ---恢复内容开始--- 标题格式:一级标题   中文数字加.例如 一. 二级标题  中文数字加:   例如二: 三级标题  小写数字加.  例如3. 使用方法: 打开PPT  按alt+f11,打开 ...

  4. nodejs入门API之fs模块

    fs模块下的类与FS常量 fs模块下的主要方法 fs的Promise API与FileHandle类 一.fs模块下的类 1.1 fs.Dir:表示目录流的类,由 fs.opendir().fs.op ...

  5. ajax请求的五个步骤

    创建XMLHttpRequest异步对象 var xhr = new XMLHttpRequest() 设置回调函数 xhr.onreadystatechange = callback 使用open方 ...

  6. 一组简单好看的css3渐变按钮

    主要代码如下: body { background:#fff } /* Mixins */ /* bg shortcodes */ .bg-gradient1 span,.bg-gradient1:b ...

  7. KVM虚拟机高级设置——10 快照、克隆、替换磁盘

    查看虚拟机磁盘文件 [root@CentOS2 ~]# cd /var/lib/libvirt/images/ [root@CentOS2 images]# ll -h total 13G -rw-r ...

  8. HDU - 6242 Geometry Problem (几何,思维,随机)

    Geometry Problem HDU - 6242 Alice is interesting in computation geometry problem recently. She found ...

  9. linux getpid _getpid()

    getpid是一种函数,功能是取得进程识别码,许多程序利用取到的此值来建立临时文件,以避免临时文件相同带来的问题. 函数功能:取得进程识别码 相关函数:fork,kill,getpid 头文件:旧版本 ...

  10. 开发神技能 | Python Mock 的入门

    Mock是什么 Mock这个词在英语中有模拟的这个意思,因此我们可以猜测出这个库的主要功能是模拟一些东西.准确的说,Mock是Python中一个用于支持单元测试的库,它的主要功能是使用mock对象替代 ...