上海市计算机学会竞赛平台2025年2月月赛丙组数阵交换

题目描述

Alice 有一个 2×n2×n 的数字阵列,也就是两行,每行 nn 个数的矩阵。因为排列的性质是优美的,所以 Alice 让每行初始都是 1∼n1∼n 的排列。

静止的数阵再优美也会看腻,所以 Alice 尝试对这个数阵做最简单的变换:交换一列中的两个数字。当然,经过若干次交换后,Alice 仍然希望这个数阵的两行都是 1∼n1∼n 的排列。

Alice 每天都希望看到不同的优美的数阵,所以请算出通过任意次(可以是 00 次)交换一列中的两个数字,能造出多少个不同的优美的数阵。称两个优美的数阵不同,当且仅当存在某一列在其中一个数阵中最终执行了交换,而另一个数阵没有。

由于答案可能很大,你只需要输出其对 109+7109+7 取模后的值。

输入格式

第一行一个整数 TT 表示数据组数,对于每组数据:

第一行一个整数 nn。

第二、三行每行 nn 个数字 pi,jpi,j​,分别表示数阵两行的元素。

输出格式

对于每组数据,输出一行一个整数表示答案对 109+7109+7 取模后的值。

数据范围

对于 30%30% 的数据,1≤T≤101≤T≤10,2≤n≤182≤n≤18。

对于 60%60% 的数据,1≤T≤101≤T≤10,2≤n≤10002≤n≤1000。

对于 100%100% 的数据,1≤T≤1041≤T≤104,2≤n≤4×1052≤n≤4×105,∑n≤4×105∑n≤4×105,1≤pi,j≤n1≤pi,j​≤n,p1,p2p1​,p2​ 分别构成 1∼n1∼n 的排列。

样例数据

输入:

2
4
1 2 3 4
4 3 2 1
5
1 3 5 2 4
2 4 1 3 5

输出:

4
2

说明:

样例解释:对于第二组数据,只有不交换和同时交换每一列中的两个数字才能使得最终得到的数阵是优美的。

详见代码:

#include <bits/stdc++.h>
using namespace std;
int a[400005];
int b[400005];
int c[400005];
int f(int x) 
{
  int mod = 1e9 + 7;
  if (x == 0) return 1;
  long long ret = f(x / 2);
  if (x % 2 == 0) return ret * ret % mod;
  else return 2 * ret * ret % mod;
}
int main() 
{
  int t, n, q;
  cin >> t;
  while(t--)
  {
    cin >> n;
    for(int i = 1; i <= n; i++)
    {
      cin >> a[i];
    }
    for(int i = 1; i <= n; i++) 
    {
      cin >> b[i];
    }
    for(int i = 1; i <= n; i++)
    {
      c[a[i]] = b[i];
    }
    int cnt = 0;
    for(int i = 1; i <= n; i++)
    {
      if (c[i] != 0) 
      {
        cnt++;
        int t = c[i];
        int s = c[i];
        while(c[t] != s) 
        {
          int x = c[t];
          c[t] = 0;
          t = x;
        }
      }
    }
    cout << f(cnt) << endl;
  }
  return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值