PA 2012 Final Round tas题解
题目大意:每组数据共有3行。
第一行有一个正整数n。
第二行有n个正整数A_1, A_2, ..., A_n表示置换A。
第三行有n个正整数B_1, B_2, ..., B_n表示排列B。判断能否达到B。n<=1000000
思考过程:这道题也是模拟赛中遇到的,刚开始,很显然的想出了置换群,并且发现了几种可以达到的充分且必要条件(这里我们将b数组重新定义为i最后处在的位置)
(1)a,b必在一个置换群中
(2)x≡bi(mod ai)其中x为置换次数,ai,bi为每一个置换群的大小,和需要变换的最小次数
到了这一步,就不知道怎么做了。。。。。。
看完标程后,终于知道了其中的奥秘
题解:将ai分解质因数,因为x mod ab=c可以推出x mod a=c mod a,所以,我们可以记录每一个质数的余数,再进行判断,首先要用线性筛求出每个数的最小质数(这样可以节约时间)然后再分解,具体看代码。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<cstring> 3 #include<cmath> 4 #include<algorithm> 5 #include<cstdio> 6 using namespace std; 7 const int maxn=1000005; 8 int n; 9 int a[maxn]; 10 int f[maxn]; 11 int num[maxn]; 12 int all[maxn]; 13 int b[maxn]; 14 char tmp[20]; 15 int p[maxn]; 16 int col; 17 int t; 18 bool flag; 19 void read(int &x){ 20 char ch = getchar(); while (ch < '0' || ch > '9') ch = getchar(); 21 for (x = 0; ch >= '0' && ch <= '9'; ch = getchar()) x = x*10+ch-48; 22 } 23 int gcd(int x,int y) 24 { 25 if(y==0)return x; 26 return gcd(y,x%y); 27 } 28 struct eq2{ int r, p, a; }e2[7100000]; 29 bool cmp(eq2 u,eq2 v) 30 { 31 if(u.p!=v.p)return u.p<v.p; 32 return u.a>v.a; 33 } 34 int l2; 35 int prm[11000000], lp; 36 int fac[11000000]; 37 void init(){ 38 for(int i=2;i<=1000000;i++){ 39 //cout<<i<<endl; 40 if (!fac[i]){ prm[++lp] = i; fac[i] = lp;} 41 for(int j=1;j<=lp;j++) 42 { 43 //cout<<"find"; 44 if (prm[j]*i > 1000000) break; 45 fac[prm[j]*i] = j; 46 if (fac[i] == j) break; 47 } 48 } 49 } 50 bool solve() 51 { 52 int l2=0; 53 for(int i=1;i<=col;i++) 54 { 55 int t=all[i]; 56 while(t!=1) 57 { 58 //cout<<t<<endl; 59 int ff=fac[t]; 60 //cout<<ff<<endl; 61 e2[++l2].p=ff; 62 e2[l2].a=1; 63 while(fac[t]==ff) 64 { 65 t/=prm[ff]; 66 e2[l2].a*=prm[ff]; 67 } 68 e2[l2].r=p[i]%e2[l2].a; 69 70 } 71 } 72 // cout<<l2<<endl; 73 sort(e2+1,e2+l2+1,cmp); 74 for(int i=1;i<l2;i++) 75 { 76 if(e2[i].p==e2[i+1].p) 77 { 78 if (e2[i].r%e2[i+1].a != e2[i+1].r){return false;} 79 } 80 } 81 return true; 82 } 83 int main() 84 { 85 // freopen("ever.in","r",stdin); 86 // freopen("ever.out","w",stdout); 87 init(); 88 // cout<<fac[4]<<endl; 89 while(scanf("%d",&n)!=EOF) 90 { 91 gets(tmp); 92 flag=true; 93 for(int i=1;i<=n;i++) 94 read(a[i]); 95 memset(f,0,sizeof(f)); 96 memset(p,0,sizeof(p)); 97 col=0; 98 for(int i=1;i<=n;i++) 99 { 100 if(f[i])continue; 101 f[i]=++col; 102 t=1; 103 num[i]=t; 104 int j=a[i]; 105 while(!f[j]) 106 { 107 t++; 108 num[j]=t; 109 f[j]=col; 110 j=a[j]; 111 } 112 all[col]=t; 113 } 114 for(int i=1;i<=n;i++) 115 { 116 int x; 117 read(x); 118 b[x]=i; 119 } 120 for(int i=1;i<=n;i++) 121 { 122 int x=b[i]; 123 //cout<<i<<" "<<x<<endl; 124 if(f[i]!=f[x]) 125 { 126 flag=false; 127 128 } 129 else 130 { 131 if(!p[f[i]]) 132 { 133 p[f[i]]=(num[x]-num[i]+all[f[i]])%all[f[i]]; 134 } 135 else 136 { 137 if((num[x]-num[i]+all[f[i]])%all[f[i]]!=p[f[i]]) 138 { 139 flag=false; 140 } 141 } 142 } 143 } 144 // for(int i=1;i<=col;i++)cout<<p[i]<<" "<<all[i]<<endl; 145 if(!flag){puts("Forever");continue;} 146 if(solve())puts("Ever");else puts("Forever"); 147 } 148 return 0; 149 }