1. 程式人生 > 實用技巧 >Bogo Sort(2020牛客暑期多校五)

Bogo Sort(2020牛客暑期多校五)

Bogo Sort

Problem:

Today Tonnnny the monkey learned a new algorithm called Bogo Sort. The teacher gave Tonnnny the code of Bogo sort:

bool is_sorted(int a[], int n) {
    for (int i = 1; i < n; i++) {
        if (a[i] < a[i - 1]) {
            return false;
        }
    }
    return true;
}
void bogo_sort(int a[], int n) {
    while (!is_sorted(a, n)) {
        shuffle(a, a + n);
    }
} 

The teacher said the shuffle function is to uniformly randomly permute the array with length , and the algorithm's expectation complexity is \(O(n \cdot n!)\).

However, Tonnnny is a determined boy — he doesn't like randomness at all! So Tonnnny improved Bogo Sort. He had chosen one favourite permutation

with length , and he replaced the random shuffle with shuffle of , so the improved algorithm, Tonnnny Sort, can solve sorting problems for length array — at least Tonnnny thinks so.

int p[N] = {....}; // Tonnnny's favorite permutation of n
void shuffle(int a[], int n) {
    int b[n];
    for (int i = 0; i < n; i++) {
        b[i] = a[i]
    }
    for (int i = 0; i < n; i++) {
        a[i] = b[p[i]];
    }
}

void tonnnny_sort(int a[], int n) {
    assert (n == N); // Tonnnny appointed!
    while (!is_sorted(a, n)) {
        shuffle(a, a + n);
    }
}

Tonnnny was satsified with the new algorithm, and decided to let you give him a different array of length every day to sort it with Tonnnny Sort.

You are the best friend of Tonnnny. Even though you had found the algorithm is somehow wrong, you want to make Tonnnny happy as long as possible. You're given \(N,\ p\), and you need to calculate the maximum number of days that Tonnnny will be happy, since after that you can't give Tonnnny an array that can be sorted with Tonnnny Sort and didn't appeared before.

The answer may be very large. Tonnnny only like numbers with at most digits, so please output answer mod \(10^N\) instead.

Input:

The first line contains one integer \(N (1 \leq N \leq 10^5)\).

The second line contains integer indicating , which forms a permutation of \(1, 2, \cdots, N\).

Output:

The maximum number of days that Tonnnny will be happy, module \(10 ^ N\).

Example:

Input

5
1 2 3 4 5

Output

1

Input

6
2 3 4 5 6 1

Output

6

題解:

題意:對於一個置換序列有多少種排列可以通過若干次置換,變成1到n的排列。

如果一個置換中沒有環,則只有一種可能。

如果一個置換中有一個環,且環長為3則可以找到三種排列。

如果一個置換有兩個環,且環長分別為2,則可以找到兩種排列。

歸納得出,對於一個長度為n的環可以得到n個原序列,當有多個環存在時,可以找出這些環長度的lcm,由於長度總和為n,所以lcm一定不會大於n位,所以不需要取模。

Code:

/**********************************************************
* @Author: 			   Kirito
* @Date:   			   2020-07-27 16:02:08
* @Last Modified by:   Kirito
* @Last Modified time: 2020-07-27 16:21:30
* @Remark: 
**********************************************************/
#include <bits/stdc++.h>
#define lowbit(x) (x&(-x))
#define CSE(x,y) memset(x,y,sizeof(x))
#define INF 0x3f3f3f3f
#define Abs(x) (x>=0?x:(-x))
#define FAST ios::sync_with_stdio(false);cin.tie(0);
using namespace std;

typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll , ll> pll;

const int maxn=111111;
int n,m,l,t,a[maxn],ans[maxn],prim[maxn],cyl[maxn],book[maxn],bp[maxn];

void multi(int x)
{
	for(int i=1;i<=l;i++)
		ans[i]*=x;
	for(int i=1;i<l;i++)
		if(ans[i]>9)
			ans[i+1]+=ans[i]/10,ans[i]%=10;
	while(l<n&&ans[l]>9){
		ans[l+1]+=ans[l]/10;
		ans[l++]%=10;
	}
	ans[l+1]=0;
	return;
}

void getPrime()
{
	for(int i=2;i<=100000;i++){
		if(bp[i]==0){
			for(int j=i+i;j<=100000;j+=i){
				bp[j]=1;
			}
			prim[++t]=i;
		}
	}
	return;
}

int main()
{
	#ifndef ONLINE_JUDGE
	freopen("in.in","r",stdin);
	#endif
	FAST;
	getPrime();//獲取範圍內所有質數
	ans[0]=0;ans[1]=1;l=1;
	cin>>n;
	for(int i=1;i<=n;i++)
		cin>>a[i];
	//計算所有環的長度
	for(int i=1;i<=n;i++){
		if(book[i]) continue;
		book[i]=cyl[++m]=1;
		int be=a[i];
		while(be!=i){
			book[be]=1;
			cyl[m]++;
			be=a[be];
		}
	}
	//對所有環的長度進行質因數分解,得到最後的lcm因子
	CSE(bp,0);
	for(int i=1;i<=m;i++){
		for(int j=1;j<=t;j++){
			if(cyl[i]<=1) break;
			int num=0;
			while(cyl[i]%prim[j]==0){
				num++,cyl[i]/=prim[j];
			}
			bp[prim[j]]=max(bp[prim[j]],num);
		}
	}
	//將所有因子相乘得到最終結果
	for(int i=1;i<=t;i++)
		while(bp[prim[i]]--)
			multi(prim[i]);
	for(int i=l;i>=1;i--)
		cout<<ans[i];
	return 0;
}