题目链接:点击打开链接
题目大意:给出一种操作a[1],a[2],,,,a[n],代表每交换一次,1位置的数到a[1]位置,2位置的数到a[2]位置,,,
问最终交换多少次可以恢复初始的情况。
题目给出一个置换,要求置换的次数,也就是所有轮换个数的最小公倍数。首先求出所有轮换的个数,然后求最小公倍数的时候不能用gcd,因为Mod的取余太大,所以用质因子分解,统计每个质因子出现的最多次数,计算最终的值。
#include <cstdio> #include <cstring> #include <queue> #include <set> #include <vector> #include <cmath> #include <map> #include <stack> #include <algorithm> #include <time.h> using namespace std ; #pragma comment(linker, "/STACK:102400000,102400000") #define LL __int64 #define INF 0x3f3f3f3f #define PI acos(-1.0) #define maxn 3000010 const LL Mod = 3221225473 ; int a[maxn] , sum[maxn] , vis[maxn] ; int main() { int t , n , i , j , num , temp , cnt ; LL ans ; scanf("%d", &t) ; while( t-- ) { scanf("%d", &n) ; for(i = 1 ; i <= n ; i++) { scanf("%d", &a[i]) ; sum[i] = vis[i] = 0 ; } for(i = 1 ; i <= n ; i++) { if( vis[i] ) continue ; vis[i] = 1 ; num = 1 ; j = a[i] ; while( !vis[j] ) { num++ ; vis[j] = 1 ; j = a[j] ; } for(j = 2 , temp = num ; j*j <= num ; j++) { if( temp%j ) continue ; cnt = 0 ; while( temp%j == 0 ) { temp /= j ; cnt++ ; } sum[j] = max(sum[j],cnt) ; if( temp == 1 ) break ; } if( temp > 1 ) sum[temp] = max(sum[temp],1) ; } for(i = 2 , ans = 1 ; i <= n ; i++) { for(j = 0 ; j < sum[i] ; j++) ans = ans*i%Mod ; } printf("%I64d\n", ans) ; } return 0 ; }
版权声明:转载请注明出处:http://blog.csdn.net/winddreams
时间: 2024-11-07 11:46:19