Échange de comptage

Lien

https://www.acwing.com/problem/content/description/214/

Le titre

Étant donné un arrangement 1 ~ n p1, p2, ..., pn, vous pouvez effectuer plusieurs opérations, sélectionner deux entiers x, y à chaque fois, échanger px, py.

Supposons que le changement de p1, p2, ..., pn en un arrangement à croissance monotone 1,2, ..., n nécessite au moins m échanges.

Découvrez combien de méthodes de fonctionnement peuvent atteindre l'objectif ci-dessus avec seulement m échanges.

Étant donné que le résultat peut être volumineux, vous devez uniquement afficher la valeur après le module de \ (10 ​​^ 9 + 9 \) .

Par exemple, organiser \ (2,3,1 \) nécessite au moins 2 échanges pour devenir \ (1,2,3 \) . Il existe trois modes de fonctionnement, à savoir:

Première méthode: échangez d'abord le nombre \ (2,3 \) pour devenir \ (3,2,1 \) , puis échangez le numéro \ (3,1 \) pour devenir \ (1,2,3 \) .
Méthode 2: échangez d'abord le nombre \ (2,1 \) pour devenir \ (1,3,2 \) , puis échangez le numéro \ (3,2 \) pour devenir \ (1,2,3 \) .
Méthode 3: échangez d'abord le numéro \ (3,1 \) pour devenir \ (2,1,3 \) , puis échangez le numéro \ (2,1 \) pour devenir \ (1,2,3 \) .
Format d'entrée La
première ligne contient l'entier T, indiquant qu'il existe T ensembles de cas de test.

Il y aura une ligne vierge avant chaque cas de test.

Chaque scénario de test contient deux lignes, la première ligne contient l'entier n.

La deuxième ligne contient n entiers, représentant la séquence \ (p_1, p_2, ..., p_n \) .

Format de sortie
Chaque scénario de test génère un résultat et chaque résultat occupe une ligne.

Plage de données
\ (1≤n≤10 ^ 5 \)
Échantillon d'entrée:

3

3
2 3 1

4
2 1 4 3

2
1 2

Exemple de sortie:

3
2
1

Des idées

L'idée est de connecter le nombre \ (a [j] = i \) à un bord non dirigé vers i, ce qui générera des anneaux \ (cnt \) , et enfin nous diviserons les anneaux \ (cnt \) en n Bague.

Lemme: tout d'abord un \ (K \) de division de simple anneau en points \ (K \) ième boucle nécessite \ (k-1 \) échange secondaire

Pour un anneau, nous pouvons choisir deux points à échanger en deux petits anneaux.
Soit \ (f [i] \) le nombre de solutions qui divisent l'anneau de longueur i en i auto-chaînes avec le nombre minimum d'échanges.
Soit \ (T (x, y) \) le nombre de solutions pour diviser un anneau de longueur: \ (x + y \) en deux anneaux de longueur x, y. En supposant qu'il existe des méthodes x + y, on peut constater que lorsque x = y, la moitié des méthodes sont symétriques. Ce \ (x = y \) lorsque \ (T (x, y) = x \) , ou \ (T (x, y)
= x + y \) fonctionnant anneau interférence x complémentaire et la bague y, nous x La disposition de l'étape x-1 dans l'anneau et de l'étape y-1 sur l'anneau y est une disposition complète d'un ensemble double.

\ [f [i] = \ sum_ {x + y = i} T (x, y) × f [x] × f [y] × \ frac {(i-2)!} {(x-1)! × (y-1)!} \]

Il y a des anneaux cnt, et la longueur de chaque anneau est \ (l [i] \). La réponse finale est:

\ [ans = (\ prod_ {i = 1} ^ {cnt} f [i]) × \ frac {(nk)!} {\ prod_ {i = 1} ^ {cnt} (l [i] -1) !} \]

Même après avoir analysé cette étape, la complexité est toujours \ (O (n ^ 2) \) .
En jouant la table (non, la solution, nous pouvons voir que f [i] = \ (i ^ {i-2} \) , grâce à la puissance rapide : La nouvelle complexité temporelle est \ (O (nlogn) \)

Code

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=100010,mod=1e9+9;
int a[N],n,st[N],l[N],d;
int fac[N],f[N];
int qmi(int a,int b){
    int res=1;
    while(b){
        if(b&1) res=(LL)res*a%mod;
        a=(LL)a*a%mod;
        b>>=1;
    }
    return res;
}
void dfs(int u){
    d++;
    st[u]=1;
    if(!st[a[u]])  dfs(a[u]);
}
void init(){
    fac[0]=1;
    f[1]=1;
    fac[1]=1;
    for(int i=2;i<N;++i){
        f[i]=qmi(i,i-2);
        fac[i]=(LL)fac[i-1]*i%mod;
    }
}
int main(){
    int T;
    init();
    scanf("%d",&T);
    while(T--){
        memset(st,0,sizeof st);
        scanf("%d",&n);
        for(int i=1;i<=n;++i){
            scanf("%d",&a[i]);
        }
        int cnt=0;
        for(int i=1;i<=n;++i){
            if(!st[i]) {
                d=0;
                dfs(i);
                l[++cnt]=d;
            }
        }
        int ans=fac[n-cnt]%mod;
        for(int i=1;i<=cnt;++i){
            ans=(LL)ans*f[l[i]]%mod*(LL)qmi(fac[l[i]-1],mod-2)%mod;
        }

        cout<<ans<<endl;
    }
    return 0;
}

Je suppose que tu aimes

Origine www.cnblogs.com/jjl0229/p/12741769.html
conseillé
Classement