CF1534C Little Alawn's Puzzle 题解

题目传送门

题目大意

给出一个 2×n 的矩阵,要求交换这个矩阵之中同一列的两个数字(当然可以交换多次,也可以不换),交换后要求每一行每一列都不能有相同的数字。求方法数量除以 109+7 的余数。

题目解析

如果有一列有相同的数字,肯定是 0
现在考虑一下答案不为 0 的情况。
由于每一行都是一个全排列,所以我们需要在交换的时候保证有一个数字从上面换到了下面,那么这个数字肯定要再换上去一个,这样我们就可以发现,有几列必须同时换,我们可以通过搜索来确定必须一起交换的列,这样就可以把所有的 n 列分成 x 个部分,由于这 n 个数字都是全排列,所以不存在某一列不属于这 x 部分,答案显然就是 2x
搜索的时候我们可以开个桶来优化查找的过程。

代码:

#include<cstdio>
#include<cstring>
#define maxn 400039
#define MOD 1000000007
using namespace std;
//#define debug
typedef int Type;
typedef long long ll;
inline Type read(){
Type sum=0;
int flag=0;
char c=getchar();
while((c<'0'||c>'9')&&c!='-') c=getchar();
if(c=='-') c=getchar(),flag=1;
while('0'<=c&&c<='9'){
sum=(sum<<1)+(sum<<3)+(c^48);
c=getchar();
}
if(flag) return -sum;
return sum;
}
int T,n,a[maxn],b[maxn];
int vis[maxn],t[maxn],ans;
ll pow(int a,int x){
ll res=1,tmp=a;
while(x){
if(x&1) res=res*tmp%MOD;
tmp=(tmp*tmp)%MOD;
x>>=1;
}
return res;
}
int check(){
for(int i=1;i<=n;i++)
if(a[i]==b[i]) return 1;
return 0;
}
void dfs(int x){
if(vis[x]) return;
vis[x]=1;
dfs(t[a[x]]);
}
int main(){
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
T=read();
while(T--){
n=read(); ans=0;
for(int i=1;i<=n;i++) a[i]=read();
for(int i=1;i<=n;i++) b[i]=read();
if(check()){
printf("0\n");
continue;
}
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++)
t[b[i]]=i;
for(int i=1;i<=n;i++)
if(!vis[i]){
dfs(i);
ans++;
}
printf("%lld\n",pow(2,ans));
}
return 0;
}
posted @   jiangtaizhe001  阅读(185)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示