正解:数论

解题报告:

传送门!

首先考虑最终的状态是固定的,所以可以知道初始状态的每个数要去哪个地方,就可以考虑给每个数$a$连一条边,指向一个数$b$,表示$a$最后要移至$b$所在的位置

显然每个数只会有一条出边,也只会有一条入边,所以会构成若干条环然后现在的目标就相当于是要通过最少的次数使所有边都变成自环

然后考虑这个交换操作,就相当于是交换两条边的终点

欧克把题目转化完了下面考虑解题

先证明这样一个结论:一个长度为$n$的环要变成$n$个自环至少需要$n-1$步

证明如下:

考虑用数学归纳法

首先长度为2的环要变成2个自环显然是1步

现在考虑若已证明对长度$<k$的环都成立

则对于长度为k的环,显然随意交换两条边的终点后就变成了一个长度为$x$的环和一个长度为$y$的环,且$x+y=k$

那么分别对这两个环都有最少步骤为$(x-1)+(y-1)=k-2$

再加上第一步交换两条边的终点的操作,总的步骤就要$k-2+1=k-1$步

得证(,,,这个证明挺弱智的我$jio$得

接着考虑设$f[x]:$拆长度为$x$的环为$x$个自环的方案数

为了表达方便再设个$g[x][y]$表示长度为$x+y$的环拆成长为$x$的环和长为$y$的环的方案数

首先显然有$g[x][y]=\left\{\begin{matrix}\frac{n}{2}(x=y)\\n(x\neq y)\end{matrix}\right.$

瞎证明下趴,下面为了表达方便提前解释下,交换点对的意思就是交换终点为这两个点的边的终点(,,,有点绕,怪我语文太差$TT$

显然当$x\neq y$的时候

对任意一个点$x$,会有两个点$y_{1}$,$y_{2}$满足交换$\left ( x,y \right )$之后能拆成一个大小为x的环和一个大小为y的环

然后再考虑重复,就每条边会被枚举两次(显然?就两个断点分别作为起点枚举一次嘛$QwQ$,所以就有$g[x][y]=\frac{n\cdot 2}{2}=n$

然后当$x=y$的时候,就显然只有一个点$y$了,所以就是$g[x][y]=\frac{n}{2}$

证毕

然后考虑$f[x]$的递推式?

不难想到$f[x]=\sum_{i=1}^{\frac{x}{2}}g[i][x-i]\cdot f[i]\cdot f[x-i]\cdot \frac{(x-2)!}{(i-1)!\cdot (x-i-1)!}$

再瞎证下$QAQ$

其实前面都不太难get,就枚举拆成的环有多大,然后拆成大小为$i,x-i$的方案数是$g[i][x-i]$,然后内部拆的方案是$f[i]\cdot f[x-i]$

主要大概是要解释下后面这个 $ \frac{(n-2)!}{ (i-1)! \cdot (n-i-1)!} $

就因为两个环是互相独立互不影响的,所以显然可以先做一步第一个环的,再做一步第二个环的,这样子,所以总共有$(n-2)$步就有$(n-2)!$条方案

但考虑到事实上在分别做两个小环的时候就已经考虑到这个问题已经乘过了,所以就再除以一个$(i-1)!\cdot (n-i-1)!$

(一个$upd:$过了一段时间之后重新来看这题发现我是呆呆,,,?这不就是组合数嘛我在想啥???????$/dk/dk/dk$

但是实际上这儿有个优化,,,因为这个复杂度实际上是过不去的,复杂度$O(n^{2})$的,但是可以打表找规律得$f[i]=i^{i-2}$

不会证啊$QAQ$那就不证了趴$QAQ$

最后考虑因为是有若干个环,同样是因为环之间互不影响可以先做一步这个环的再做一步那个环的这样子,所以最后的$ans$就是 $ (\prod_{i=1}^{k} f_{l_i}) \cdot \dfrac{(n-k)!}{\prod_{i=1}^k(l_i-1)!} $

$aya$好像忘记说$l_i$辣,,,,就是说每个环的大小辣

那就做完辣?等下放代码吼$QwQ!$

#include<bits/stdc++.h>
using namespace std;
#define il inline
#define gc getchar()
#define t(i) edge[i].to
#define int long long
#define ri register int
#define rb register bool
#define rc register char
#define rp(i,x,y) for(ri i=x;i<=y;++i)
#define my(i,x,y) for(ri i=x;i>=y;--i)
#define e(i,x) for(ri i=head[x];i;i=edge[i].nxt) const int N=1e5+,mod=1e9+;
int head[N],ed_cnt,ln[N],ln_cnt,as,n,jc[N],inv[N];
bool vis[N];
struct ed{int to,nxt;}edge[N<<]; il int read()
{
rc ch=gc;ri x=;rb y=;
while(ch!='-' && (ch>'' || ch<''))ch=gc;
if(ch=='-')ch=gc,y=;
while(ch>='' && ch<='')x=(x<<)+(x<<)+(ch^''),ch=gc;
return y?x:-x;
}
il int power(ri x,ri y){if(y<)return ;ri ret=;while(y){if(y&)ret=1ll*ret*x%mod;x=1ll*x*x%mod;y>>=;}return ret;}
il void pre()
{
jc[]=;rp(i,,N-)jc[i]=1ll*jc[i-]*i%mod;
inv[N-]=power(jc[N-],mod-);my(i,N-,)inv[i]=1ll*inv[i+]*(i+)%mod;
}
il void ad(ri x,ri y){edge[++ed_cnt]=(ed){x,head[y]};head[y]=ed_cnt;}
int dfs(ri x,ri fa){if(vis[x])return ;vis[x]=;e(i,x)return dfs(t(i),x)+;} signed main()
{
// freopen("4778.in","r",stdin);freopen("4778.out","w",stdout);
int T=read();pre();
while(T--)
{
memset(vis,,sizeof(vis));memset(head,,sizeof(head));ed_cnt=;ln_cnt=;
n=read();rp(i,,n)ad(i,read());rp(i,,n)if(!vis[i])ln[++ln_cnt]=dfs(i,);
as=jc[n-ln_cnt];rp(i,,ln_cnt)as=1ll*as*power(ln[i],ln[i]-)%mod*inv[ln[i]-]%mod;
printf("%lld\n",as);
}
return ;
}

这儿是代码,,,

洛谷P4778 Counting swaps 数论的更多相关文章

  1. 乘法原理,加法原理,多重集的排列数(多个系列操作穿插的排列数) 进阶指南 洛谷p4778

    https://www.luogu.org/problemnew/solution/P4778 非常好的题目,囊括了乘法加法原理和多重集合排列,虽然最后使用一个结论解出来的.. 给定一个n的排列,用最 ...

  2. 洛谷P4562 [JXOI2018]游戏 数论

    正解:数论 解题报告: 传送门! 首先考虑怎么样的数可能出现在t(i)那个位置上?显然是[l,r]中所有无法被表示出来的数(就约数不在[l,r]内的数嘛QwQ 所以可以先把这些数筛出来 具体怎么筛的话 ...

  3. 洛谷P3104 Counting Friends G 题解

    题目 [USACO14MAR]Counting Friends G 题解 这道题我们可以将 \((n+1)\) 个边依次去掉,然后分别判断去掉后是否能满足.注意到一点, \(n\) 个奶牛的朋友之和必 ...

  4. 洛谷P1134 阶乘问题[数论]

    题目描述 也许你早就知道阶乘的含义,N阶乘是由1到N相乘而产生,如: 12! = 1 x 2 x 3 x 4 x 5 x 6 x 7 x 8 x 9 x 10 x 11 x 12 = 479,001, ...

  5. luogu P4778 Counting swaps

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

  6. 洛谷P2398 GCD SUM [数论,欧拉筛]

    题目传送门 GCD SUM 题目描述 for i=1 to n for j=1 to n sum+=gcd(i,j) 给出n求sum. gcd(x,y)表示x,y的最大公约数. 输入输出格式 输入格式 ...

  7. 洛谷P2231 [HNOI2002]跳蚤 [数论,容斥原理]

    题目传送门 跳蚤 题目描述 Z城市居住着很多只跳蚤.在Z城市周六生活频道有一个娱乐节目.一只跳蚤将被请上一个高空钢丝的正中央.钢丝很长,可以看作是无限长.节目主持人会给该跳蚤发一张卡片.卡片上写有N+ ...

  8. 洛谷P1414 又是毕业季 [数论]

    题目传送门 又是毕业季 题目背景 “叮铃铃铃”,随着高考最后一科结考铃声的敲响,三年青春时光顿时凝固于此刻.毕业的欣喜怎敌那离别的不舍,憧憬着未来仍毋忘逝去的歌.1000多个日夜的欢笑和泪水,全凝聚在 ...

  9. 洛谷 - P1403 - 约数研究 - 数论

    https://www.luogu.org/problemnew/show/P1403 可以直接用线性筛约数个数求出来,但实际上n以内i的倍数的个数为n/i的下整,要求的其实是 $$\sum\limi ...

随机推荐

  1. C语言学习及应用笔记之五:C语言typedef关键字及其使用

    在C语言中有一个typedef关键字,其用来定义用户自定义类型.当然,并不是真的创造了一种数据类型,而是给已有的或者符合型的以及复杂的数据类型取一个我们自己更容易理解的别名.总之,可以使用typede ...

  2. CentOS7中MariaDB重置密码

    虚拟机里的MariaDB忘记密码了,连接不上,只能重置MariaDB的密码,步骤参考网络 [root@localhost ~]# mysql -uroot -p Enter password: ERR ...

  3. select获取选中的option(包含value和text,重点是text怎么获取)

    简单描述:后台需要获取到select标签选择的内容,也就是text,该怎么取呢?很简单. 代码: //hml代码<div class="col-md-6"> <l ...

  4. springboot集成mybatis源码分析-mybatis的mapper执行查询时的流程(三)

    例: package com.example.demo.service; import com.example.demo.dao.UserDao; import com.example.demo.do ...

  5. 【转】 为什么我们做分布式使用Redis

    绝大部分写业务的程序员,在实际开发中使用 Redis 的时候,只会 Set Value 和 Get Value 两个操作,对 Redis 整体缺乏一个认知.这里对 Redis 常见问题做一个总结,解决 ...

  6. ajax与后台交互案例

    BBS项目 //BBS项目,注册页面ajax请求 // 1.实现照片预览 $("#up_myhead").change(function () { // 获取input选择的文件 ...

  7. Spring设置定时任务时,关于执行时间的规则设置

    been需要在xml文件中进行配置 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE bean ...

  8. Knockout中ko.utils中处理数组的方法集合

    每一套框架基本上都会有一个工具类,如:Vue中的Vue.util.Knockout中的ko.utils.jQuery直接将一些工具类放到了$里面,如果你还需要更多的工具类可以试试lodash.本文只介 ...

  9. Codeforces Round #524 (Div. 2) F

    题解: 首先这个东西因为强制在线区间查询 所以外面得套线段树了 然后考虑几条线段怎么判定 我们只需要按照右端点排序,然后查询的时候查找最右节点的前缀最大值就可以了 然后怎么合并子区间信息呢 (刚开始我 ...

  10. Eclipse4.8.0的svn插件离线安装说明

    Eclipse4.8.0离线安装Subclipse(SVN插件)的方法: Subclipse迁到github上了,地址:https://github.com/subclipse/subclipse/w ...