刚开始一直把题意看错了。。。体测完智商急剧下降
正确理解题意以后自己写一直wa,而且并不知道是哪里的问题,在网上看了一下其他人写的改了改自己的就过了,可是之前的还是不知道为什么不对。
题意大概就是有一个置换群,问运算多少次会出现给定的样子。我们可以求出每个元素需要运算多少次到达给定的样子,记为 r [ i ] r[i] r[i],再计算出运算多少次是一个循环,记为 m [ i ] m[i] m[i],则最后的次数x为x%m=r的同余方程的解。
AC代码
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<ctime>
#include<climits>
#include<queue>
#include<vector>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
const ll INF=0x3f3f3f3f;
const ll MAXN=1e3+5;
ll a[MAXN],b[MAXN],m[MAXN],r[MAXN],vis[MAXN],tmp[MAXN],nxt[MAXN];
ll n,ans;
void ex_gcd(ll a,ll b,ll &d,ll &x,ll &y)
{
if(!b) {d=a; x=1; y=0;}
else{ex_gcd(b,a%b,d,y,x); y-=(a/b)*x;}
}
bool ex_crt(ll &M,ll &R)
{
M=1; R=0; ll d,k,kk,c;
for(ll i=1;i<=n;i++)
{
if(m[i]==0 && r[i]==0) continue;
c=r[i]-R;
ex_gcd(M,m[i],d,k,kk);
if(c%d) return false;
k=c/d*k%(m[i]/d); R+=k*M; M*=m[i]/d; R%=M;
}
R=(R+M)%M;
return true;
}
void test()
{
printf("============================\n");
printf("m: "); for(ll i=1;i<=n;i++)printf("%d ",m[i]); printf("\n");
printf("r: "); for(ll i=1;i<=n;i++)printf("%d ",r[i]); printf("\n");
printf("============================\n");
}
bool solve()
{
ll t,cnt;
memset(m,0,sizeof(m));
memset(r,-1,sizeof(r));
/*
for(ll i=1;i<=n;i++)
{
cnt=0; t=i;
if(a[i]==i)
{
if(b[i]!=i) return false;
m[i]=0; r[i]=0; continue;
}
while(a[t]!=i)
{
if(r[i]==-1 && t==b[i]) r[i]=cnt;
t=a[t]; cnt++;
}
m[i]=cnt+1; if(r[i]==-1) return false;
}
*/
memset(vis,false,sizeof(vis));
for(int i=1;i<=n;i++) tmp[i]=i;
cnt=0;
while(cnt!=n)
{
for(int i=1;i<=n;i++)
{
nxt[i]=tmp[a[i]]; if(vis[i]) continue;
m[i]++;
if(nxt[i]==i)
{
cnt++; vis[i]=true;
}
if(nxt[i]==b[i]) r[i]=m[i];
}
for(int i=1;i<=n;i++) tmp[i]=nxt[i];
}
for(int i=1;i<=n;i++)
{
if(r[i]<0) return false; r[i]%=m[i];
}
//test();
ll M,R;
if(ex_crt(M,R))
ans=R;
else return false;
return true;
}
int main()
{
while(~scanf("%lld",&n) && n)
{
bool flag=true;
for(ll i=1;i<=n;i++) scanf("%lld",&a[i]);
for(ll i=1;i<=n;i++)
{
scanf("%lld",&b[i]);
if(flag && b[i]!=flag) flag=false;
}
if(flag)
{
printf("0\n");
continue;
}
if(solve())
{
printf("%lld\n",ans);
}
else
{
printf("-1\n");
}
}
return 0;
}
我自己写的代码是求m和r的部分有问题,并不知道为什么。。。难受