1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
| const int N=1e6+10,P=1e9+7;
int n,m; int Pow[N]; int A[N],L[N],C,R[N],D; int vis[N];
int Calc(int c1,int c2){ int t=min(c1,c2),ans=t; c1-=t,c2-=t; if(c1) ans+=c1/3*2; if(c2) ans+=c2; return ans; }
int Calc(int c1,int c2,int c4){ return c4+Calc(c1+c4,c2); }
int main(){ rep(i,*Pow=1,N-1) Pow[i]=1ll*Pow[i-1]*3%P; rep(_,1,rd()) { n=rd(); rep(i,1,n) A[i]=rd(),vis[i]=0; C=0; rep(i,1,n) if(!vis[i]) { int c=0; for(int j=i;!vis[j];j=A[j]) c++,vis[j]=1; L[++C]=c; } if(n%3==0) { printf("%d ",Pow[n/3]); int ans=0; rep(i,1,C) { while(L[i]>3) L[i]-=3,ans++; if(L[i]==3) L[i]=0; } int c1=0,c2=0; rep(i,1,C) if(L[i]==1) c1++; else if(L[i]==2) c2++; ans+=Calc(c1,c2); printf("%d\n",ans); continue; }
if(n%3==2) { printf("%d ",Pow[n/3]*2%P); int cnt=n/3,ans=0; rep(i,1,C) { while(cnt && L[i]>3) L[i]-=3,cnt--,ans++; if(L[i]==3 && cnt) L[i]=0,cnt--; } int c1=0,c2=0; rep(i,1,C) if(L[i]==1) c1++; else if(L[i]==2) c2++; if(c2) c2--; else c1-=2,ans++; ans+=Calc(c1,c2); printf("%d\n",ans); continue; } printf("%lld ",Pow[(n-4)/3]*4ll%P); int cnt=(n-4)/3,c3=0,ans=0; rep(i,1,C) { while(cnt && L[i]>4) L[i]-=3,cnt--,ans++; if(L[i]==3 && cnt) L[i]=0,cnt--; } int c1=0,c2=0,c4=0; rep(i,1,C) if(L[i]==1) c1++; else if(L[i]==2) c2++; else if(L[i]==3) c3++; else if(L[i]==4) c4++; if(c3) ans++; else { int w=1e9; if(c4) cmin(w,Calc(c1,c2,c4-1)); if(c1>=4) cmin(w,Calc(c1-4,c2,c4)+2); if(c2>=2) cmin(w,Calc(c1,c2-2,c4)); if(c1>=2 && c2) cmin(w,Calc(c1-2,c2-1,c4)+1); ans+=w; } printf("%d\n",ans); } }
|