P4778 Counting swaps

这题最后的通项公式是Cayley公式,求大佬解答一下有什么关系吗???

分析:

  • 每个 pip_ipi​ 向 iii 连边,便构成一张由若干个简单环组成的无向图,目标状态是 nnn 个自环的图
引理:把一个长度为n的环变成n个自环,最少需要n-1次交换操作(证明略)
  • 设 f[n]f[n]f[n] 表示用最少的步数将一个长度为 nnn 的环变成 nnn 个自环,共有多少种操作方法

    若将该环拆分成长度为 xxx 和 yyy 的两个环 (x+y=n)(x+y=n)(x+y=n) ,设 T(x,y)T(x,y)T(x,y) 表示有多少种交换方法,容易发现:
    T(x,y)={n/2(x==y)n(x!=y)T(x,y)= \begin{cases} n/2\ (x==y)\\ n\ (x!=y)\\ \end{cases} T(x,y)={n/2 (x==y)n (x!=y)​
    两者各自变成自环的方法数为 f[x]f[x]f[x] 和 f[y]f[y]f[y] ,步数为 x−1x-1x−1 和 y−1y-1y−1

    再根据多重集的排列数、加法原理和乘法原理:
    f[n]=∑x+y=nT(x,y)∗f[x]∗f[y]∗(n−2)!(x−1)!(y−1)!f[n]=\sum_{x+y=n} T(x,y)*f[x]*f[y]*\frac{(n-2)!}{(x-1)!(y-1)!} f[n]=x+y=n∑​T(x,y)∗f[x]∗f[y]∗(x−1)!(y−1)!(n−2)!​

  • 再回到题目,若最初的排列由长度为 l1,l2,...,lkl_1,l_2,...,l_kl1​,l2​,...,lk​ 的 kkk 个环构成:
    ans=f[l1]∗f[l2]∗...∗f[lk]∗(n−k)!(l1−1)!∗(l2−1)!∗...∗(lk−1)!ans=f[l_1]*f[l_2]*...*f[l_k]*\frac{(n-k)!}{(l_1-1)!*(l_2-1)!*...*(l_k-1)!} ans=f[l1​]∗f[l2​]∗...∗f[lk​]∗(l1​−1)!∗(l2​−1)!∗...∗(lk​−1)!(n−k)!​

  • 但如果直接这么算,时间复杂度 (O(n2))(O(n^2))(O(n2)) ,会超时!

    这个时候便需要万能神 OEISOEISOEIS 网站了,将 f[n]f[n]f[n] 的前几项输入到 oeisoeisoeis 中,得到通项公式 f[n]=nn−2f[n]=n^{n-2}f[n]=nn−2 , 便可优化到 (O(nlogn))(O(nlogn))(O(nlogn))

  • 好东西要分享OEIS

打表的代码:

#include <bits/stdc++.h>
//#define int long long
using namespace std;typedef long long ll;
const int N=1e5+5, mo=1e9+9;int ksm(int a,int b,int p=mo)
{int ans=1;while(b){if(b&1) ans=(ll)ans*a%p;b>>=1; a=(ll)a*a%p;}return ans;
}
int cal(int x,int y)
{if(x==y) return x;return x+y;
}
int f[N], fc[N];
void init()
{fc[0]=1;for(int i=1;i<=1000;i++) fc[i]=(ll)fc[i-1]*i%mo;f[1]=f[2]=1;for(int i=3;i<=100;i++){for(int j=1;j<=i>>1;j++){int inv=ksm((ll)fc[j-1]*fc[i-j-1]%mo, mo-2);f[i]=(f[i]+(ll)f[i-j]*f[j]%mo*fc[i-2]%mo*inv%mo*cal(i-j,j)%mo)%mo;}}for(int i=1;i<=10;i++) cout<<f[i]<<endl;
}
signed main()
{init();return 0;
}

Ac code:

#include <bits/stdc++.h>
using namespace std;typedef long long ll;
const int N=1e5+5, mo=1e9+9;int ksm(int a,int b,int p=mo)
{int ans=1;while(b){if(b&1) ans=(ll)ans*a%p;b>>=1; a=(ll)a*a%p;}return ans;
}
int fc[N], f[N];
void init()
{fc[0]=1;for(int i=1;i<N;i++) fc[i]=(ll)fc[i-1]*i%mo;f[1]=1;for(int i=2;i<N;i++) f[i]=ksm(i,i-2);
}
int a[N], vis[N], cn[N];
int dfs(int u) // dfs查环的大小
{vis[u]=1;if(vis[a[u]]) return 1;return 1+dfs(a[u]);
}
void solve()
{int n;cin>>n;for(int i=1;i<=n;i++) {cin>>a[i];vis[i]=0;}int tot=0;for(int i=1;i<=n;i++){if(!vis[i]) cn[++tot]=dfs(i);}int ans=fc[n-tot]; for(int i=1;i<=tot;i++){int inv=ksm(fc[cn[i]-1],mo-2);ans=(ll)ans*f[cn[i]]%mo*inv%mo;}cout<<ans<<endl;
}
signed main()
{ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);init();int T;cin>>T;while(T--) solve();return 0;
}

P4778 Counting swaps (组合数学,打表推通项公式,OEIS)相关推荐

  1. Counting swaps

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

  2. 【组合数学】递推方程 ( 常系数线性非齐次递推方程 的 非齐次部分是 多项式 与 指数 组合方式 | 通解的四种情况 )

    文章目录 一.常系数线性非齐次递推方程 的 非齐次部分是 多项式 与 指数 组合方式 二.递推方程通解的四种情况 一.常系数线性非齐次递推方程 的 非齐次部分是 多项式 与 指数 组合方式 如果 &q ...

  3. 【组合数学】递推方程 ( 递推方程示例 2 汉诺塔 | 递推方程示例 3 插入排序 )

    文章目录 一.递推方程示例 2 汉诺塔 二.递推方程示例 3 插入排序 一.递推方程示例 2 汉诺塔 Hanoi 问题 : 递推方程为 : T(n)=2T(n−1)+1T(n) =2 T(n-1) + ...

  4. 【组合数学】递推方程 ( 特解形式 | 特解求法 | 特解示例 )

    文章目录 一.特解形式与求法 二.特解形式与求法 示例 一.特解形式与求法 H(n)−a1H(n−1)−⋯−akH(n−k)=f(n)H(n) - a_1H(n-1) - \cdots - a_kH( ...

  5. 【算法讲26:特征方程】求齐次线性一阶递推与二阶递推通项公式 | HDU 2021多校一 Pass!

    [算法讲26:特征方程]求一阶递推与二阶递推通项公式 引入 齐次线性一阶递推 齐次线性二阶递推 题目解法 下文中详细证明略,可以看 [数列]特征方程与特征根 引入 HDU 2021多校一 Pass! ...

  6. 【一些常用的递推通项公式的求法】

    1.前言:在很多题目里会涉及到递推公式的使用,然而大多数递推公式都是有很强的前后依赖性,第n项的求解依赖于n前边的几项.比如大名鼎鼎的fib数列.但是很多时候,我们要O(1)公式.本文简单的谈一下一些 ...

  7. 【组合数学】递推方程 ( 通解定义 | 无重根下递推方程通解结构定理 )

    文章目录 一.通解定义 二.无重根下递推方程通解结构定理 一.通解定义 递推方程解的形式 : 满足 H(n)−a1H(n−1)−a2H(n−2)−⋯−akH(n−k)=0H(n) - a_1H(n-1 ...

  8. 【组合数学】递推方程 ( 递推方程示例 1 | 列出递推方程 )

    文章目录 一.递推方程示例 1 二.递推方程示例小结 一.递推方程示例 1 编码系统使用 888 进制数字 , 对信息编码 , 888 进制数字只能取值 0,1,2,3,4,5,6,70,1,2,3, ...

  9. 【组合数学】递推方程 ( 递推方程内容概要 | 递推方程定义 | 递推方程示例说明 | 斐波那契数列 )

    文章目录 一.递推方程 内容概要 二.递推方程 定义 三.递推方程 示例 四.斐波那契数列 ( Fibnacci ) 一.递推方程 内容概要 递推方程 内容概要 : 递推方程定义 递推方程实例 常系数 ...

  10. UVA 10910 Marks Distribution(组合数学 或 递推)

    题意:一个人N门课程的总成绩为T,每门课程的最低成绩为P,求一共有多少种可能的分配方法. 题解:可以先求出超出的部分 T = T - n*p:剩余的相当于n个里面每个科目放0,1分等. 这题我只懂了递 ...

最新文章

  1. IT兄弟连 JavaWeb教程 JSON和JSON字符串
  2. YumRepo Error: All mirror URLs are not using ftp, http[s] or file. Eg. /HTML/ 标签: yum 2014-05-26
  3. SuperMap注册流程记录
  4. 公网mysql_(看图)为什么无法通过公网登录MySQL?
  5. SpeedyCloud研发总监李孟:不要让底层细节被上层打败
  6. 计算机二级web题目(1)--web基础
  7. [读书笔记] -《C++ API设计》第6章 C++用法
  8. append从一个添加到另一_麻城一总投资1.5亿项目开工建设,另一项目预计9月底开工,还有一个年产值14亿的5G项目快速推进中...
  9. [testNG]Cannot find class in classpath解决方法
  10. C# winfrom单击事件弹出浏览器
  11. testcookie-nginx-module
  12. 华为鸿蒙系统支持什么手机_华为鸿蒙系统支持的手机型号大全,鸿蒙系统2.0支持手机型号汇总[图]...
  13. .NET 调整图片尺寸(Resize)各种方法
  14. H264编解码算法在网络视频传输中的应用
  15. 为什么计算机连不上无线网络,笔记本为什么连不上无线网|笔记本电脑无法连接WiFi的多种解决方法...
  16. 【重磅】2021年SCI影响因子滚烫式公布!各领域TOP期刊!(附下载链接)
  17. General error: 1366 Incorrect string value: '\xF0\x9F\x98\x8A' for column
  18. 英特尔多核平台编程优化大赛报告
  19. gerrit删除Group和Project
  20. 网站代码该如何优化?

热门文章

  1. Windows命令行工具cmder配置
  2. 哨兵系列卫星_国外卫星典型应用
  3. 我对国内两大购书站点的感受(dearbook和china-pub)
  4. “站长也疯狂,开车盛宴”——如何选择运维产品
  5. 【Python - wxpython】- 卫星通信系统链路计算软件
  6. flash mx拖拽实例_Flash MX 2004的ScatterBug命令面板
  7. 百度知心搜索–基于深度数据瓦解和用户行为分析的搜索引擎
  8. 大数据点点滴滴积少成多---进阶之路
  9. 小程序源码:独立后台带分销功能月老办事处交友盲盒-多玩法安装简单
  10. Win32 Application和Win32 Console Application区别