「杂题乱刷」CF1534C

题目链接

CF1534C Little Alawn's Puzzle

题意简述

给定两个排列 \(a,b\),你可以进行的操作为交换一列中的两个数字,你需要求出操作后能够满足没有相同数字在同一行的数阵能的个数并对 \(10^9+7\) 取模。

解题思路

我们先举两个例子:

1 2 3 4 5
1 2 3 4 5

这个例子的方案数很显然,可以抽象成一个五位的 \(01\) 字符串的方案数,答案为 \(2^5\)

1 2 3 4 5
3 1 2 4 5

这个例子我们发现,要是条件成立,一定会去交换第 \(1 \sim 3\) 位的数字或不交换第 \(1 \sim 3\) 位的数字,一定会去交换第 \(4\) 位的数字或不交换第 \(4\) 位的数字,一定会去交换第 \(5\) 位的数字或不交换第 \(5\) 位的数字,答案为 \(2^3\)

而这个例子我们可以用一张图表示:

通过上面两个例子,容易看出,答案一定是 \(2\) 的正整数次幂,然后我们可以将问题转化成每次连接 \(a_i,b_i\) 两个点,记连通块的数量为 \(x\),容易看出最后答案是 \(2^x\),最后我们直接用并查集维护即可。

参考代码

#include<bits/stdc++.h>
using namespace std;
long long t,n,ans,a[400010],u[400010],v[400010];
long long find(long long x)
{
	if(a[x]==x)
		return x;
	return a[x]=find(a[x]);
}
#define mod (int)1e9+7
#define lowbit(x) x&-x
#define pb push_back
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define endl '\n'
#define QwQ return 0;
int main()
{
	IOS;
	cin>>t;
	while(t--)
	{
		ans=1;
		cin>>n;
		for(int i=1;i<=n;i++)
			a[i]=i;
		for(int i=1;i<=n;i++)
			cin>>u[i];
		for(int i=1;i<=n;i++)
			cin>>v[i];
		for(int i=1;i<=n;i++)
			a[find(u[i])]=find(v[i]);
		map<int,int>mp;
		for(int i=1;i<=n;i++)
			if(!mp[find(i)])
				mp[find(i)]=1,ans*=2,ans%=mod;	
		cout<<ans<<endl;
	}
	QwQ;
}
posted @ 2023-11-28 16:43  wangmarui  阅读(4)  评论(0编辑  收藏  举报