码迷,mamicode.com
首页 > 其他好文 > 详细

P4778 Counting Swaps 题解

时间:2020-01-26 19:12:01      阅读:66      评论:0      收藏:0      [点我收藏+]

标签:wap   情况   count   组合   复杂度   递归   code   print   const   

第一道 A 掉的严格意义上的组合计数题,特来纪念一发。
第一次真正接触到这种类型的题,给人感觉好像思维得很发散才行……


对于一个排列 \(p_1,p_2,\dots,p_n\),对于每个 \(i\)\(p_i\) 连一条边,可以发现整个构成了一个由若干环组成的图,目标是将这些环变为自环。
引理:把长度为 \(n\) 的环变为 \(n\) 个自环,最少交换次数为 \(n-1\)
用归纳法证,对于当前情况,任意一次交换都将其拆为两个环,由淘汰赛法则可知引理成立。
\(F_n\) 表示在最少交换次数下把长度为 \(n\) 的环变为 \(n\) 个自环,有多少种交换方式。由前所述,我们每次都将其拆为两个环,不妨设两个环长度为 \(x,y\),并记 \(T(x,y)\) 表示有多少种方法可将一个长度为 \(n\) 的环变为长度为 \(x,y\) 的两个环,那么当 \(n\) 为偶数且 \(x=y\) 时有 \(T(x,y)=\frac{n}{2}\),其他情况 \(T(x,y)=n\)。由于 \(x\) 环与 \(y\) 环的操作互不干扰,两边的操作可以随意排列,因此这里就是一个多重集的全排列。
于是有了递归表达式: \[F_n=\sum_{x+y=n}\left(T(x,y)F_xF_y\frac{(n-2)!}{(x-1)!(y-1)!}\right)\] 对于题目中的所有 \(k\) 个环,记它们的长度为 \(\{l_k\}\),最终答案为: \[\prod^{k}_{i=1}F_{l_{i}}\dfrac{(n-k)!}{\prod^{k}_{i=1}(l_i-1)!}\] 还没完,经过JOJO的洗礼之后发现 \(F_n=n^{n-2}\)!复杂度立马降为 \(O(n\log n)\)……
(找环这个骚操作是照题解区 dalao 学的,只能 orz

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int N=1e5+5;
const ll mod=1e9+9;
int n,a[N],L[N],cnt;
ll fac[N]={1,1},F[N]={0,1};
bool vis[N];

ll qpow(ll bas,ll p)
{
    ll res=1; bas%=mod;
    for(;p;p>>=1)
    {
        if(p&1) res=res*bas%mod;
        bas=bas*bas%mod;
    }
    return res;
}

int dfs(int x)
{
    vis[x]=1;
    if(vis[a[x]]) return 1;
    return dfs(a[x])+1;
}

int main()
{
    int T; scanf("%d",&T);
    for(int i=2;i<N;++i)
        fac[i]=i*fac[i-1]%mod,
        F[i]=qpow(i,i-2)%mod;
    while(T--)
    {
        memset(vis,0,sizeof(vis));
        cnt=0;
        scanf("%d",&n);
        for(int i=1;i<=n;++i)
            scanf("%d",&a[i]);
        for(int i=1;i<=n;++i)
            if(!vis[i]) L[++cnt]=dfs(i);
        ll ans=fac[n-cnt];
        for(int i=1;i<=cnt;++i)
            ans=ans*F[L[i]]%mod*qpow(fac[L[i]-1],mod-2)%mod;
        printf("%lld\n",ans);
    }
    return 0;
}

P4778 Counting Swaps 题解

标签:wap   情况   count   组合   复杂度   递归   code   print   const   

原文地址:https://www.cnblogs.com/wzzyr24/p/12234527.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!