リンク
https://www.acwing.com/problem/content/description/214/
タイトル
1〜nの配置p1、p2、...、pnを指定すると、複数の操作を実行し、2つの整数x、yを毎回選択して、px、pyを交換できます。
p1、p2、...、pnを単調に増加する配列1、2、...、nに変更するには、少なくともm回の交換が必要であるとします。
m回の交換で上記の目標を達成できる操作方法の数を調べます。
結果は大きくなる可能性があるため、\(10 ^ 9 + 9 \)の係数の後に値を出力するだけで済みます。
たとえば、\(2,3,1 \)を配置するには、\(1,2,3 \)になるために少なくとも2つの交換が必要です。つまり、3つの操作方法があります。
方法1:最初に数値\(2,3 \)を交換して\(3,2,1 \)にし、次に数値\(3,1 \)を交換して\(1,2,3 \)にします。
方法2:最初の交換ディジタル\(2,1 \)に(1,3,2 \)\、次に数字を交換\(3,2 \)に(1,2,3 \)\。
方法3:最初に数値\(3,1 \)を交換して\(2,1,3 \)にし、次に数値\(2,1 \)を交換して\(1,2,3 \)にします。
入力形式
最初の行には整数Tが含まれており、T組のテストケースがあることを示します。
各テストケースの前に空白行があります。
各テストケースには2行が含まれ、最初の行には整数nが含まれています。
2行目には、シーケンス\(p_1、p_2、...、p_n \)を表すn個の整数が含まれています。
出力形式
各テストケースは結果を出力し、各結果は1行を占めます。
データ範囲
\(1≤n≤10^ 5 \)
入力サンプル:
3
3
2 3 1
4
2 1 4 3
2
1 2
出力例:
3
2
1
アイデア
\(a [j] = i \)数をiへの無向エッジに接続すると、\(cnt \)リングが生成され、最後に\(cnt \)リングがnポイントに分割されます。リング。
補題:最初に\(k \)ポイントを持つ単純なリングを\(k \)自己ループに分割します。これには\(k-1 \)交換が必要です
リングの場合、2つのポイントを選択して2つの小さなリングに交換できます。
セット\(F [I]は、\)最小スイッチング周波数を表し、iは、リングの長さは、i番目の列からのプログラムの数に分割されています。
セットが\(T(x、y)は\)の長さを表す:(X + Y \)\ xの2つのループ長に分割され、Yは、プログラムループの数です。x + yメソッドがあると仮定すると、x = yの場合、メソッドの半分は対称的であることがわかります。ことを(X = Y \)\場合\(T(X、Y)= X \) 、または\(T(X、Y)
= X + Y \) X環およびY環相補的干渉を操作、我々は、Xリングのx-1ステップとyリングのy-1ステップの配置は、ダブルセットの完全な配置です。
cntリングがあり、各リングの長さは\(l [i] \)です。最終的な答えは次のとおりです。
このステップを分析した後でも、複雑さは\(O(n ^ 2)\)のままです。
表を再生することで(いいえ、解、f [i] = \(i ^ {i-2} \)が高速なパワーでわかります:新しい時間の複雑さは\(O(nlogn)\)です
コード
#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;
}