zoukankan      html  css  js  c++  java
  • 《算法竞赛进阶指南》0x36组合计数 计数交换

    题目链接:https://www.acwing.com/problem/content/214/

    给出一个排列打乱之后的顺序,要求将其还原成升序全排列的方法数,通过计算,将一个长度为n的环变成自环需要用n-1步,将一个长度为n的环变成自环可能的步数有n^(n-2)种,假设这个给出的全排列中环的数量是k,那么一共需要n-k步。由于每次步数的选择中,每一类的是没有顺序的,所以需要利用多重集的公式进行去重。

    代码:

    #include<iostream>
    #include<cstdio>
    #include<string.h>
    using namespace std;
    const int maxn = 100010;
    const int mod = 1000000009;
    typedef long long ll;
    ll jc[maxn];
    int n;
    int a[maxn],p[maxn];
    bool vis[maxn];
    ll power(ll a,ll b){
        ll ans=1;
        b%=mod;
        while(b){
            if(b&1)
                ans=(ans*a)%mod;
            a=(a*a)%mod;
            b>>=1;
        }
        return ans;
    }
    int main(){
        jc[0]=1;
        for(int i=1;i<=maxn-1;i++)jc[i]=(jc[i-1]*i)%mod;
        int T;
        cin>>T;
        while(T--){
            cin>>n;
            int cnt=0;
            ll ans=1;
            memset(vis,0,sizeof(vis));
            for(int i=1;i<=n;i++)scanf("%d",&a[i]);
            for(int i=1;i<=n;i++)p[i]=a[i];
            for(int i=1;i<=n;i++){
                if(vis[i])continue;
                int len=1;    
                vis[i]=1;
                for(int j=p[i];j!=i;j=p[j])vis[j]=1,len++;
                cnt++;
                ans=(ans*(len==1?1:power(len,len-2)))%mod;
                ans=(ans*power(jc[len-1],mod-2))%mod;//求解逆元 
            }
            ans=(ans*jc[n-cnt])%mod;
            cout<<ans<<endl;
        }    
        return 0;
    }
  • 相关阅读:
    直方图内最大矩阵
    P1578 奶牛浴场
    P1569 [USACO11FEB]属牛的抗议Generic Cow Prote…
    P1566 加等式
    P1564 膜拜
    P1541 乌龟棋
    P1537 弹珠
    Response.AddHeader使用实例
    LSPCI具体解释分析
    介绍一款开源的类Excel电子表格软件
  • 原文地址:https://www.cnblogs.com/randy-lo/p/13279808.html
Copyright © 2011-2022 走看看