题目
给定一个长度为n(n<=1e6)的序列,第i个数ai(1<=ai<=n),
操作:你可以将当前i位置的数和a[i]位置的数交换
交换可以操作任意次,求所有本质不同的数组的数量,答案对1e9+7取模
思路来源
力扣群 潼神
心得
感觉已经说的很详尽了,甚至没什么需要补充的地方...
不难发现,自环的情况和>=2的环的情况是统一的,所以dfs找环即可
组合题更多的是一种无从下手的感觉,需要多培养手玩性质的能力
比如,发现a->b->c到a->c,b->b这个性质,然后再着手计数
代码
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define per(i,a,b) for(int i=(a);i>=(b);--i)
typedef long long ll;
typedef double db;
typedef pair<ll,int> P;
#define fi first
#define se second
#define pb push_back
#define dbg(x) cerr<<(#x)<<":"<<x<<" ";
#define dbg2(x) cerr<<(#x)<<":"<<x<<endl;
#define SZ(a) (int)(a.size())
#define sci(a) scanf("%d",&(a))
#define pt(a) printf("%d",a);
#define pte(a) printf("%d\n",a)
#define ptlle(a) printf("%lld\n",a)
#define debug(...) fprintf(stderr, __VA_ARGS__)
typedef unsigned ui;
//typedef __uint128_t L;
typedef unsigned long long L;
typedef unsigned long long ull;
const int N=1e6+10,mod=1e9+7;
int n,v,to[N],deg[N];
vector<int>e[N];
int stk[N],c,ans=1;
bool vis[N],in[N];
void dfs(int u){if(!u)return;stk[++c]=u;in[u]=1;vis[u]=1;int v=to[u];if(in[v]){//环的情况 统一了自环的情况int res=1,sub=0;while(c){int w=stk[c--];in[w]=0;res=1ll*res*(deg[w]+1)%mod;sub=(sub+deg[w])%mod;if(w==v)break;}res=(res+mod-sub)%mod;ans=1ll*ans*res%mod;}if(!vis[v])dfs(v);
}
int main(){sci(n);rep(i,1,n){sci(v);to[i]=v;deg[v]++;}rep(i,1,n){if(!vis[i]){dfs(i);}while(c){int w=stk[c--];in[w]=0;ans=1ll*ans*(deg[w]+1)%mod;}}printf("%d\n",ans);return 0;
}