题目
也就是给一个置换,问有多少个排列可以通过该置换变成有序的排列,结果对1en取模
输入n,置换序列;输出结果。
思路
1.建一张n个节点的图,从i向pi连一条有向边。设环的大小为环中所包含的节点数,则该图中所有环大小的lcm就是答案。每次置换都可以看成环中的元素向环的正向移动一位,那么当所有元素都回到原位时就是一个循环了。
2.置换是固定的,所以只需要求出一个有序的序列(1 2 3 …n)可以通过多少次置换再次回到原来的样子即可
3.每个数经过的位置是一个循环,每个处于循环中的数都可以经过相同的次数回到原来的位置,所以只需要求出每个环中的一个数需要的次数就可以了,然后求出最小公倍数
4.涉及大数,要用大数模板。模数很吓人,但取大数的后n位输出即可。
关于环
比如 p 为 321,a 为 321 ,那么 a 被 p置换一次后为 123 ,再被置换一次为321 ,又变为了原数组,即 13 构成一个环,2自身构成一个环。
大数模板
代码(长得吓人主要是因为大数模板和全得一批的头文件)
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<fstream>
#include<set>
#include<map>
#include<sstream>
#include<iomanip>
#define ll long long
using namespace std;
#define maxn 100100
#define MAXN 9999
#define MAXSIZE 500 //最大长度
#define DLEN 4
class BigNum {
private:
int a[210000]; //控制大数的位数
int len; //长度
public:
BigNum() { len = 1; memset(a, 0, sizeof(a)); } //构造函数
void XD();
BigNum(const int);
BigNum(const long long int);
BigNum(const char*);
BigNum(const string&);
BigNum(const BigNum&); //拷贝构造函数
BigNum& operator = (const BigNum&); //重载赋值运算符
BigNum& operator = (const int&);
BigNum& operator = (const long long int&);
friend istream& operator >> (istream&, BigNum&); //重载输入运算符
friend ostream& operator << (ostream&, BigNum&); //重载输出运算符
template<typename T> BigNum operator << (const T&) const;
template<typename T> BigNum operator >> (const T&) const;
BigNum operator + (const BigNum&) const; //重载加法运算符,大数加大数
BigNum operator - (const BigNum&) const; //重载减法运算符,大数减大数
BigNum operator * (const BigNum&) const; //重载乘法运算符,大数乘大数
bool operator > (const BigNum& b)const; //重载大于
bool operator < (const BigNum& b) const; //重载小于
bool operator == (const BigNum& b) const; //重载等于符号
template<typename T> BigNum operator / (const T&) const; //重载除法运算符,大数除整数
template<typename T> BigNum operator ^ (const T&) const; //大数的n次方
template<typename T> T operator % (const T&) const; //大数对int取模
template<typename T> BigNum operator + (const T& b) const { BigNum t = b; t = *this + t; return t; }
template<typename T> BigNum operator - (const T& b) const { BigNum t = b; t = *this - t; return t; }
template<typename T> BigNum operator * (const T& b) const { BigNum t = b; t = (*this) * t; return t; }
template<typename T> bool operator < (const T& b) const { BigNum t = b; return ((*this) < t); }
template<typename T> bool operator > (const T& b) const { BigNum t = b; return ((*this) > t); }
template<typename T> bool operator == (const T& b) const { BigNum t = b; return ((*this) == t); }
bool operator <= (const BigNum& b) const { return (*this) < b || (*this) == b; }
bool operator >= (const BigNum& b) const { return (*this) > b || (*this) == b; }
bool operator != (const BigNum& b) const { return !((*this) == b); }
template<typename T> bool operator >= (const T& b) const { BigNum t = b; return !((*this) < t); }
template<typename T> bool operator <= (const T& b) const { BigNum t = b; return !((*this) > t); }
template<typename T> bool operator != (const T& b) const { BigNum t = b; return !((*this) == t); }
BigNum& operator += (const BigNum& b) { *this = *this + b; return *this; }
BigNum& operator -= (const BigNum& b) { *this = *this - b; return *this; }
BigNum& operator *= (const BigNum& b) { *this = *this * b; return *this; }
template<typename T> BigNum& operator /= (const T& b) { *this = *this / b; return *this; }
template<typename T> BigNum& operator %= (const T& b) { *this = *this % b; return *this; }
template<typename T> BigNum& operator += (const T& b) { *this = *this + b; return *this; }
template<typename T> BigNum& operator -= (const T& b) { *this = *this - b; return *this; }
template<typename T> BigNum& operator *= (const T& b) { *this = *this * b; return *this; }
template<typename T> BigNum& operator ^= (const T& b) { *this = *this ^ b; return *this; }
BigNum operator ++ (int) { BigNum t = *this; *this += 1; return t; }
BigNum operator -- (int) { BigNum t = *this; *this -= 1; return t; }
BigNum& operator -- () { *this -= 1; return *this; }
BigNum& operator ++ () { *this += 1; return *this; }
template<typename T> BigNum& operator <<= (const T& b) { *this = *this << b; return *this; }
template<typename T> BigNum& operator >>= (const T& b) { *this = *this >> b; return *this; }
template<typename T> BigNum friend operator + (const T& a, const BigNum& b) { BigNum t = a; t = t + a; return t; }
template<typename T> BigNum friend operator - (const T& a, const BigNum& b) { BigNum t = a; t = t - b; return t; }
template<typename T> BigNum friend operator * (const T& a, const BigNum& b) { BigNum t = a; t = t * b; return t; }
template<typename T> friend bool operator < (const T& a, const BigNum& b) { return b > a; }
template<typename T> friend bool operator > (const T& a, const BigNum& b) { return b < a; }
template<typename T> friend bool operator <= (const T& a, const BigNum& b) { return b >= a; }
template<typename T> friend bool operator >= (const T& a, const BigNum& b) { return b <= a; }
template<typename T> friend bool operator == (const T& a, const BigNum& b) { return b == a; }
template<typename T> friend bool operator != (const T& a, const BigNum& b) { return b != a; }
void print(); //输出大数
int Size(); //返回大数长度
int the_first(); //返回第一个数字
int the_last(); //返回最后一位数字
int to_int(); //转化为整数
long long int to_long();
string to_String(); //转化为string类型
//char* to_char();
};
BigNum::BigNum(const int b) //将一个int类型的变量转化为大数
{
int c, d = b;
len = 0;
memset(a, 0, sizeof(a));
while (d > MAXN) {
c = d - (d / (MAXN + 1)) * (MAXN + 1);
d = d / (MAXN + 1);
a[len++] = c;
}
a[len++] = d;
}
BigNum::BigNum(const long long int b)
{
long long int c, d = b;
len = 0;
memset(a, 0, sizeof(a));
while (d > MAXN) {
c = d - (d / (MAXN + 1)) * (MAXN + 1);
d = d / (MAXN + 1);
a[len++] = c;
}
a[len++] = d;
}
BigNum::BigNum(const string& s)
{
int t, k, index, l, i;
memset(a, 0, sizeof(a));
l = s.size();
len = l / DLEN;
if (l % DLEN)
len++;
index = 0;
for (i = l - 1; i >= 0; i -= DLEN) {
t = 0;
k = i - DLEN + 1;
if (k < 0) k = 0;
for (int j = k; j <= i; j++)
t = t * 10 + s[j] - '0';
a[index++] = t;
}
}
BigNum::BigNum(const char* s) //将一个字符串类型的变量转化为大数
{
int t, k, index, l, i;
memset(a, 0, sizeof(a));
l = strlen(s);
len = l / DLEN;
if (l % DLEN)
len++;
index = 0;
for (i = l - 1; i >= 0; i -= DLEN) {
t = 0;
k = i - DLEN + 1;
if (k < 0) k = 0;
for (int j = k; j <= i; j++)
t = t * 10 + s[j] - '0';
a[index++] = t;
}
}
BigNum::BigNum(const BigNum& b) : len(b.len) //拷贝构造函数
{
memset(a, 0, sizeof(a));
for (int i = 0; i < len; i++)
a[i] = b.a[i];
}
BigNum& BigNum::operator = (const BigNum& n) //重载赋值运算符,大数之间进行赋值运算
{
len = n.len;
memset(a, 0, sizeof(a));
for (int i = 0; i < len; i++)
a[i] = n.a[i];
return *this;
}
BigNum& BigNum::operator = (const int& num)
{
BigNum t(num);
*this = t;
return *this;
}
BigNum& BigNum::operator = (const long long int& num)
{
BigNum t(num);
*this = t;
return *this;
}
void XD()
{
cout << "A hidden egg! Good luck for u!" << endl;
}
template<typename T> BigNum BigNum::operator << (const T& b) const
{
T temp = 1;
for (int i = 0; i < b; i++)
temp *= 2;
BigNum t = (*this) * temp;
return t;
}
template<typename T> BigNum BigNum::operator >> (const T& b) const
{
T temp = 1;
for (int i = 0; i < b; i++)
temp *= 2;
BigNum t = (*this) / temp;
return t;
}
BigNum BigNum::operator + (const BigNum& b) const //两个大数之间的相加运算
{
BigNum t(*this);
int i, big;
big = b.len > len ? b.len : len;
for (i = 0; i < big; i++) {
t.a[i] += b.a[i];
if (t.a[i] > MAXN) {
t.a[i + 1]++;
t.a[i] -= MAXN + 1;
}
}
if (t.a[big] != 0)
t.len = big + 1;
else
t.len = big;
return t;
}
BigNum BigNum::operator - (const BigNum& b) const //两个大数之间的相减运算
{
int i, j, big;
bool flag;
BigNum t1, t2;
if (*this > b) {
t1 = *this;
t2 = b;
flag = 0;
}
else {
t1 = b;
t2 = *this;
flag = 1;
}
big = t1.len;
for (i = 0; i < big; i++) {
if (t1.a[i] < t2.a[i]) {
j = i + 1;
while (t1.a[j] == 0)
j++;
t1.a[j--]--;
while (j > i)
t1.a[j--] += MAXN;
t1.a[i] += MAXN + 1 - t2.a[i];
}
else
t1.a[i] -= t2.a[i];
}
t1.len = big;
while (t1.a[t1.len - 1] == 0 && t1.len > 1) {
t1.len--;
big--;
}
if (flag)
t1.a[big - 1] = 0 - t1.a[big - 1];
return t1;
}
BigNum BigNum::operator * (const BigNum& b) const //两个大数之间的相乘运算
{
BigNum ret;
int i, j, up;
int temp, temp1;
for (i = 0; i < len; i++) {
up = 0;
for (j = 0; j < b.len; j++) {
temp = a[i] * b.a[j] + ret.a[i + j] + up;
if (temp > MAXN) {
temp1 = temp - temp / (MAXN + 1) * (MAXN + 1);
up = temp / (MAXN + 1);
ret.a[i + j] = temp1;
}
else {
up = 0;
ret.a[i + j] = temp;
}
}
if (up != 0) ret.a[i + j] = up;
}
ret.len = i + j;
while (ret.a[ret.len - 1] == 0 && ret.len > 1)
ret.len--;
return ret;
}
template<typename T> BigNum BigNum::operator / (const T& b) const
{
BigNum ret;
T i, down = 0;
for (i = len - 1; i >= 0; i--) {
ret.a[i] = (a[i] + down * (MAXN + 1)) / b;
down = a[i] + down * (MAXN + 1) - ret.a[i] * b;
}
ret.len = len;
while (ret.a[ret.len - 1] == 0 && ret.len > 1)
ret.len--;
return ret;
}
template<typename T> T BigNum::operator % (const T& b) const
{
T i, d = 0;
for (i = len - 1; i >= 0; i--) {
d = ((d * (MAXN + 1)) % b + a[i]) % b;
}
return d;
}
template<typename T> BigNum BigNum::operator^(const T& n) const //大数的n次方运算
{
BigNum t, ret(1);
int i;
if (n < 0) return 0;
if (n == 0)
return 1;
if (n == 1)
return *this;
int m = n;
while (m > 1) {
t = *this;
for (i = 1; (i << 1) <= m; i <<= 1)
t = t * t;
m -= i;
ret = ret * t;
if (m == 1) ret = ret * (*this);
}
return ret;
}
bool BigNum::operator > (const BigNum& b) const //大数和另一个大数的大小比较
{
int tot;
if (len > b.len)
return true;
else if (len == b.len) {
tot = len - 1;
while (a[tot] == b.a[tot] && tot >= 0)
tot--;
if (tot >= 0 && a[tot] > b.a[tot])
return true;
else
return false;
}
else
return false;
}
bool BigNum::operator < (const BigNum& b) const
{
int tot;
if (len > b.len)
return false;
else if (len == b.len) {
tot = len - 1;
while (a[tot] == b.a[tot] && tot >= 0)
tot--;
if (tot >= 0 && a[tot] > b.a[tot])
return false;
else
return false;
}
else
return true;
}
bool BigNum::operator == (const BigNum& b) const
{
int tot = len - 1;
if (len != b.len)
return false;
while (a[tot] == b.a[tot] && tot >= 0)
tot--;
if (tot < 0)
return true;
return false;
}
int n;
void BigNum::print() //输出大数
{
int i;
if (len >= n) {
cout << a[len - 1];
for (i = len - 2; i >= len - n; i--) {
cout.width(DLEN);
cout.fill('0');
cout << a[i];
}
cout << endl;
}
else {
cout << a[len - 1];
for (i = len - 2; i >= 0; i--) {
cout.width(DLEN);
cout.fill('0');
cout << a[i];
}
cout << endl;
}
}
int BigNum::Size()
{
int t = a[len - 1], cnt = 0;
while (t) { t /= 10; cnt++; }
cnt += (len - 1) * 4;
return cnt;
}
int BigNum::the_first()
{
int t = a[len - 1];
while (t > 10) { t /= 10; }
return t;
}
int BigNum::the_last()
{
int t = a[0];
return t % 10;
}
int BigNum::to_int()
{
int i, num;
num = a[len - 1];
for (i = len - 2; i >= 0; i--)
num = num * (MAXN + 1) + a[i];
return num;
}
long long int BigNum::to_long()
{
int i;
long long int num;
num = a[len - 1];
for (i = len - 2; i >= 0; i--)
num = num * (MAXN + 1) + a[i];
return num;
}
string BigNum::to_String()
{
int i;
string s = "", tp = "";
s += to_string(a[len - 1]);
for (i = len - 2; i >= 0; i--) {
tp = to_string(a[i]);
int tot = tp.size();
tp.insert(tp.begin(), 4 - tot, '0');
s = s + tp;
}
return s;
}
int p[maxn];
int to[maxn];
int vis[maxn];
int ans;
BigNum lin, mod;
int gcd1(int x, int y) {
return y ? gcd1(y, x % y) : x;
}
int gcd(BigNum x, int y) {
return gcd1(y, x % y);
}
int main() {
lin = BigNum(0);
cin >> n;
mod = BigNum(10) ^ n;
for (int i = 1; i <= n; i++) {
scanf("%d", &p[i]);
to[p[i]] = i;
}
BigNum ans = BigNum(1);
for (int i = 1; i <= n; i++) {
if (vis[i]) continue;
int tmp = i;
int res = 0;
while (to[tmp] != i) {
vis[tmp] = 1;
tmp = to[tmp];
res++;
}
res++;
ans = ans / gcd(ans, res) * res;
}
ans.print();
return 0;
}