CF1534C Little Alawn's Puzzle 题解
题目大意
给出一个 的矩阵,要求交换这个矩阵之中同一列的两个数字(当然可以交换多次,也可以不换),交换后要求每一行每一列都不能有相同的数字。求方法数量除以 的余数。
题目解析
如果有一列有相同的数字,肯定是 。
现在考虑一下答案不为 的情况。
由于每一行都是一个全排列,所以我们需要在交换的时候保证有一个数字从上面换到了下面,那么这个数字肯定要再换上去一个,这样我们就可以发现,有几列必须同时换,我们可以通过搜索来确定必须一起交换的列,这样就可以把所有的 列分成 个部分,由于这 个数字都是全排列,所以不存在某一列不属于这 部分,答案显然就是 。
搜索的时候我们可以开个桶来优化查找的过程。
代码:
#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; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· 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工具