Pinely Round 2 (Div. 1 + Div. 2) G. Swaps(组合计数)

题目

给定一个长度为n(n<=1e6)的序列,第i个数ai(1<=ai<=n),

操作:你可以将当前i位置的数和a[i]位置的数交换

交换可以操作任意次,求所有本质不同的数组的数量,答案对1e9+7取模

思路来源

力扣群 潼神

心得

感觉已经说的很详尽了,甚至没什么需要补充的地方...

不难发现,自环的情况和>=2的环的情况是统一的,所以dfs找环即可

组合题更多的是一种无从下手的感觉,需要多培养手玩性质的能力

比如,发现a->b->c到a->c,b->b这个性质,然后再着手计数

代码

cpp 复制代码
#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;
}
相关推荐
Ryan_Adam10 天前
组合数学学习笔记
组合数学
一直学习永不止步15 天前
LeetCode题练习与总结:赎金信--383
java·数据结构·算法·leetcode·字符串·哈希表·计数
summ1ts2 个月前
组合数求法汇总
c++·数学·算法·离散数学·组合数学
Tisfy2 个月前
LeetCode 2207.字符串中最多数目的子序列:计数
算法·leetcode·字符串·题解·思维·计数
硕风和炜3 个月前
【LeetCode:3137. K 周期字符串需要的最少操作次数 | 哈希表 + 子串计数】
java·算法·leetcode·散列表·哈希表·计数
感觉画质不如…原神5 个月前
Leetcode.1735 生成乘积数组的方案数
质因数分解·组合数学
xhchen20235 个月前
第 402 场 LeetCode 周赛题解
leetcode·前缀和·动态规划·哈希·计数·树状数组
xhchen20236 个月前
第 400 场 LeetCode 周赛题解
前缀和·优先级队列·贪心·二分·排序·计数
闻缺陷则喜何志丹6 个月前
【组合数学 隔板法 容斥原理】放球问题
c++·算法·组合数学·容斥原理·隔板法·放球问题·盒子
爱欲无极1 年前
无人机低空视角:针对人群密集场景的检测、跟踪和计数技术
人工智能·无人机·计数·追踪