C. Little Alawn’s Puzzle
读了好久才读懂啥意思,一共就两行,每次操作可以交换上下两个数
前提问题解决的条件是:每行都是一个排列,并且所有列没有相同的数
问加上当前的这一个情况,在交换之后也符合问题的解一共有多少个
分析:
根据样例2我们可以发现,如果要交换数字后保证还是一个排列,必须把属于同一个集合的所有列都进行交换,显然是一道并查集,寻找一共有 sum 个集合,对于每一个集合我们可以选择操作或不操作,就是求 2 的 sum 次方。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 4e5 + 9;
const int mod = 1e9 + 7;
int n, t, _;
ll a[3][N];
int f[N];
int find(int x)
{
int r = x, j, k = x;
while(f[r] != r) r = f[r];
while(k != r)
{
j = f[k];
f[k] = r;
k = j;
}
return r;
}
ll q_power(ll a, ll n)
{
ll ans = 1;
while(n)
{
if(n & 1) ans = (ans * a) % mod;
n >>= 1;
a = (a * a) % mod;
}
return ans;
}
void work()
{
ll ans = 0;
scanf("%d", &n);
for(int i = 1; i <= n; ++i) f[i] = i;
for(int i = 1; i <= 2; ++i)
for(int j = 1; j <= n; ++j)
{
scanf("%d", &a[i][j]);
}
for(int i = 1; i <= n; ++i)
{
int xx = find(a[1][i]), yy = find(a[2][i]);
if(xx != yy)
f[xx] = yy;
}
for(int i = 1; i <= n; ++i)
if(find(i) == i) ++ans;
//cout << ans << endl;
printf("%lld\n", q_power(2, ans));
}
int main()
{
cin >> t;
for(_ = 1; _ <= t; ++_)
work();
return 0;
}
/*
1 2 3
2 3 1
*/