题意真是迷,才清楚。。mod yql
题意:Town将一个序列1….n,打乱成序列A,给你序列A,问你经过多少次置换才能 回到A。
也就是说,宏这个操作并不是直接两个数直接交换,而是进行置换的乘法。
解释下样例
1 3 2 的操作应该为 1 3 2->1 2 3->1 3 2
2 1 4 5 3 的操作 应该为 2 1 4 5 3->1 2 5 3 4->2 1 3 4 5->1 2 4 5 3->2 1 5 3 4 ->1 2 3 4 5->2 1 4 5 3
然后这个我们就是求,有多少个置换环,也就是循环节,然后把求他们长度的LCM。注意这里的lcm,用分解质因数来求,也可以用gcd直接求,ans=lcm(ans,a[i])。题目中说要用读入优化,可是我用scanf过了,用读入挂T了==(这是为啥??(可能是数据有问题吧,空格太多?
#include <cstring>
#include <cmath>
#include <algorithm>
#include <cstdio>
#include <vector>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define ll long long
const int maxn = 3000005;
const ll inf = 3221225473;
int a[maxn];
int vis[maxn];
int z[maxn];
ll pow1(ll a,ll b)
{
ll ans=1,q=a;
while(b)
{
if(b&1) ans=ans*q%inf;
q=q*q%inf;
b=b/2;
}
return ans%inf;
}
int main()
{
int T,m;
scanf("%d",&T);
while(T--)
{
mem(a,0);mem(vis,0);
scanf("%d",&m);
for(int i=1;i<=m;i++)
scanf("%d",&z[i]);
for(int i=1;i<=m;i++)
{
if(vis[i]||z[i]==i) continue;
int cnt=0;
if(!vis[i])
{
int k=z[i];
while(!vis[k])
{
cnt++;vis[k]=1;k=z[k];
}
k=(int)sqrt(cnt)+1;
for(int j=2;j<=k;j++)
{
int num=0;
while(cnt%j==0)
{
num++;
cnt=cnt/j;
}
if(a[j]<num) a[j]=num;
if(cnt==1) break;
}
if(cnt>1) a[cnt]=max(a[cnt],1);
}
}
ll ans=1;
for(ll i=1;i<=m;i++)
{
ans=ans*pow1(i,a[i])%inf;
}
printf("%I64d\n",ans);
}
return 0;
}