zoukankan      html  css  js  c++  java
  • 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 img with length img, 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 imgwith length img, and he replaced the random shuffle with shuffle of img, so the improved algorithm, Tonnnny Sort, can solve sorting problems for length imgarray — 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 imgevery 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 imgdigits, 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 imginteger indicating img, 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;
    }
    
  • 相关阅读:
    MS SQL入门基础:SQL数据库中的事务
    MS SQL入门基础:删除数据
    MS SQL入门基础:触发器的高级应用
    MS SQL入门基础:SQL Server 安全性管理的途径
    MS SQL入门基础:权限管理
    MS SQL入门基础:打开游标
    MS SQL入门基础:数据库更新添加数据
    MS SQL入门基础:游标、游标的优点和种类
    MS SQL入门基础:创建和管理视图
    MS SQL入门基础:数据库中的连接查询
  • 原文地址:https://www.cnblogs.com/LeafLove/p/13386417.html
Copyright © 2011-2022 走看看