2020牛客暑期多校(五)

https://ac.nowcoder.com/acm/contest/5670

Bogo sort

题解:https://blog.nowcoder.net/n/59a8480b4bbf4e69b1523bbaa07a0c7e

代码:来自https://ac.nowcoder.com/acm/contest/view-submission?submissionId=44402547

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
int n,l,r,cnt=1,ans,len=1,a[maxn],c[maxn],d[maxn],e[maxn],f[maxn],g[maxn],an[maxn]={0,1};
bool b[maxn];
void mul(int x)//大数乘
{
    for(int i=1;i<=len;i++) an[i]*=x;
    for(int i=1;i<len;i++)if(an[i]>9) an[i+1]+=an[i]/10,an[i]%=10;
    while(len<n&&an[len]>9) an[len+1]+=an[len]/10,an[len++]%=10;
    an[len+1]=0;
}
int main()
{
    for(int i=2;i<maxn;i++)
    {
        if(!d[i])
        {
            for(int j=i*2;j<maxn;j+=i)
                d[j]=1;
            e[++ans]=i;
        }
    }
    //素数筛求出质数 存在e数组中
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    for(int i=1;i<=n;i++)//求出每个置换群的点的个数,存在c数组中//求环的长度
    {
        l=i,r=0;
        while(!b[l])
            b[l]=1,r=1,c[cnt]++,l=a[l];
        if(r)
            cnt++;
    }
/*高精度
问题是高精度求lcm是个麻烦的事情,万幸的是,这些群的大小都是int型的,因此gcd是很好求的。
可是要用到大数除,诶这就有点麻烦了,对于一个根本忘了怎么写高精度的蒟蒻来说,除法是个难于上青天的事情。
但是蒟蒻脑子好使,可以用另一种方式来求lcm。考虑分解质因数,对于每个质数记录每个数的质因数的个数的最大值,有点绕呵,举个例子吧。
比如有2,3,42,3,42,3,4要求它们的最小公倍数,则我只要分解:
2=2,3=3,4=2*2
那么2有max(1,2)次,3有1次,因此它们的最小公倍数是2^2*3^1=12,没有问题。
它的原理是:任意一对数,它们如果有质因子相同,那么根据lcm=a*b/gcd可知,它会将公共的部分除掉,相当于对于每个质因子的个数求个max即可。
比如有质数pr,a=pr^3*……,b=pr^5*...,则它们的公共部分是pr^3,相乘之后有pr^8,除掉后有pr^5 也就是pr^{max(3,5)}
*/
    for(int i=0;i<cnt;i++)//遍历质数
    {
        for(int j=1,t=0;j<=ans&&c[i]>1;j++)//遍历每个c[i]含有这个质数
        {
            while(c[i]%e[j]==0)
                t++,c[i]/=e[j];
            f[e[j]]=max(f[e[j]],t);
            t=0;
        }
    }
    for(int i=1;i<=ans;i++)
        while(f[e[i]]--)
            mul(e[i]);
    //把每个质数乘起来
    for(int i=len;i>=1;i--)
        printf("%d",an[i]);//反着输出
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/rainartist/p/13379610.html