Counting swaps
给你一个1~n的排列,问用最少的交换次数使之变为递增排列的方案数\(mod\ 10^9+7\),1 ≤ n ≤ 10^5。
解
显然最少的交换次数不定,还得需要找到最小交换次数,而考虑到交换为复杂的过程,考虑状态的性质,所以不难想到画出,+为箭头指向方向
_ _
| + | +
2 1 4 3
+ | + |
|_| |_|
于是你会发现实际上我们的变换为递增序列,即把所有的环都变成自环,而交换两个数字即拆环,所以不难知道,一个环拆掉的最少的次数为环的大小-1(因为你对一个环进行一次交换操作,就变成了两个环,以此类推,拆成n个环,要操作n-1次)。
有了这样一个想法,于是考虑环的组合计数问题的方法,可以以拆环为状态划分来设递推方程,于是设\(f[i]\)表示长度为i的环的变成全部是自环的最少操作次数的方案数,拆成两个环又有不同的拆分方式,于是设\(T[i][j]\)表示拆成两个长i,j的环的方案数,于是我们有
\]
\]
于是,设初始序列为长\(l_1,l_2...,l_m\)的环构成的,易知
\]
但是对于f找规律,我们发现\(f[i]=i^{i-2}\),于是我们可以利用矩阵快速幂,时间复杂度应为\(O(nlog(n))\)。
参考代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#define il inline
#define ri register
#define ll long long
#define yyb 1000000009
#define lsy 1000000007
#define _ putchar('\n')
using namespace std;
int num[100001];
bool check[100001];
ll dp[100001],jc[100001],jv[100001];
il ll pow(ll,ll);
il void prepare();
template<class free>void pen(free);
template<class free>il void read(free&);
int main(){
int cjx,i,j,n,len,tot;ll ans;
prepare(),read(cjx);
while(cjx--){
read(n),memset(check,0,sizeof(check));
for(i=1;i<=n;++i)read(num[i]);tot&=0,ans=1;
for(i=1;i<=n;++i)
if(!check[i]){
j=i,++tot,len&=0;
do j=num[j],++len,check[j]|=true;
while(i!=j);
ans=ans*dp[len]%yyb*jv[len-1]%yyb;
}ans=ans*jc[n-tot]%yyb,pen(ans),_;
}
return 0;
}
template<class free>
void pen(free x){
if(x>9)pen(x/10);putchar(x%10+48);
}
il ll pow(ll x,ll y){
ll ans(1);
while(y){
if(y&1)ans=ans*x%yyb;
x=x*x%yyb,y>>=1;
}return ans;
}
void prepare(){
ri int i,j;jc[1]=jc[0]=jv[1]=jv[0]=dp[1]=1;
for(i=2;i<=100000;++i)
jc[i]=jc[i-1]*i%yyb,jv[i]=
pow(jc[i],lsy),dp[i]=pow(i,i-2);
}
template<class free>
il void read(free& x){
x&=0;ri char c;while(c=getchar(),c<'0'||c>'9');
while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
}
Counting swaps的更多相关文章
- CH3602 Counting Swaps
题意 3602 Counting Swaps 0x30「数学知识」例题 背景 https://ipsc.ksp.sk/2016/real/problems/c.html Just like yeste ...
- 洛谷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\). 请你告诉穰子,用最少的操作次数将给定 ...
- luoguP4778 Counting swaps
题目链接 题解 首先,对于每个\(i\)向\(a[i]\)连边. 这样会连出许多独立的环. 可以证明,交换操作不会跨越环. 每个环内的点到最终状态最少交换步数是 \(环的大小-1\) 那么设\(f[i ...
- 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 ...
随机推荐
- 关于键盘KeyDown事件
if (e.KeyValue==13) //如果键盘的值等于13 这里面的13是enter键 textBox2.Focus(); //焦点就跑到textbox2上面
- Vue生命周期学习
转自https://www.w3cplus.com/vue/vue-instances-and-life-cycles.html Vue实例虽然没有完全遵循MVVM模型,但Vue的设计无疑受到了它的启 ...
- 程序员必备技能:代码审查 (Google牛人谈Code Review)
在上一篇博客里我暗示自己将不在为Google工作. 我还没有决定好去哪儿-有几个非常不错的工作机会让我选择.鉴于这段时间内我不受雇于任何公司,我想我可以写点和专业相关的东西,这些东西很有趣,但是如果我 ...
- [javaSE] 数据结构(栈)
栈(stack)是一种线性存储结构,有以下特点: 1.栈中数据是按照先进后出的方式进出栈的 2.向栈中添加删除元素时,只能从栈顶进行操作 使用数组实现栈 定义一个类ArrayStack 实现入栈方法p ...
- 用户登录注册(安全)(常规、FB、google、paypal) 实战
/* 用户登录界面 */elseif ($action == 'login'){ if($_SESSION['user_id']) { ecs_header("Lo ...
- 17、多线程 (Thread、线程创建、线程池)
进程概念 *A:进程概念 *a:进程:进程指正在运行的程序.确切的来说,当一个程序进入内存运行, 即变成一个进程,进程是处于运行过程中的程序,并且具有一定独立功能. 线程的概念 *A:线程的概念 *a ...
- No Mapping For GET "xxx.do"
今天写的一个form表单提交时总是报错找不到mapping,form如下: <form action="toUpdate.do" method="post" ...
- Java8实战Lambda和Stram API学习
public class Trader{ private String name; private String city; public Trader(String n, St ...
- 【SSH网上商城项目实战16】Hibernate的二级缓存处理首页的热门显示
转自:https://blog.csdn.net/eson_15/article/details/51405911 网上商城首页都有热门商品,那么这些商品的点击率是很高的,当用户点击某个热门商品后需要 ...
- HBase—列族数据库的术语
1. 列族数据库的基本组件 键空间,行键,列,列族 2. 什么是键空间 keyspace? 键空间 keyspace 是列族数据库的顶级数据结构,它在逻辑上能够容纳列族,行键以及与之相关的其他数据结构 ...