2020牛客暑期多校训练营第五场Bogo Sort

Bogo Sort

原题请看这里

题目描述:

今天, T o n n n n y Tonnnny Tonnnny学习了一种称为 B o g o Bogo Bogo S o r t Sort Sort的新算法。 老师给了 T o n n n n y Tonnnny Tonnnny B o g o Bogo Bogo S o r t Sort Sort的代码:
2020牛客暑期多校训练营第五场Bogo Sort_第1张图片
老师说,函数 s h u f f l e shuffle shuffle是等概率地随机排列长度为 N N N的数组 a a a,这个算法的期望复杂度为 O ( n ⋅ n ! ) O(n⋅n!) O(nn!)
但是, T o n n n n y Tonnnny Tonnnny是一个坚定的男孩——他一点也不喜欢随机! 因此, T o n n n n y Tonnnny Tonnnny改进了 B o g o Bogo Bogo S o r t Sort Sort。 他选择了一个最喜欢的长度为 N N N的排列 p p p,然后用排列 p p p替换随机的 s h u f f l e shuffle shuffle,因此改进的算法, T o n n n n y Tonnnny Tonnnny S o r t Sort Sort,可以解决长度为n的数组的排序问题——至少 T o n n n n y Tonnnny Tonnnny如此认为。
2020牛客暑期多校训练营第五场Bogo Sort_第2张图片
T o n n n n y Tonnnny Tonnnny对新算法感到满意,因此决定让您每天给他一个长度为 N N N的不同数组,以使用 T o n n n n y Tonnnny Tonnnny S o r t Sort Sort对其进行排序。您是 T o n n n n y Tonnnny Tonnnny最好的朋友。 即使您发现该算法有某种错误,也希望让 T o n n n n y Tonnnny Tonnnny多快乐一会。 给定 N N N p p p,您需要计算 T o n n n n y Tonnnny Tonnnny可以开心的最大天数,因为在那之后,您将不能给 T o n n n n y Tonnnny Tonnnny一个可以用 T o n n n n y Tonnnny Tonnnny S o r t Sort Sort排序的之前没出现过的数组。答案可能非常大。 T o n n n n y Tonnnny Tonnnny只喜欢最多 N N N位的数字,因此请改为输出答案 m o d mod mod 1 0 N 10^N 10N

输入描述:

第一行包含一个整数 N N N ( ( ( 1 1 1 ≤ \leq N N N ≤ \leq 1 0 5 10^5 105 ) ) )
第二行包含 N N N个整数,表示一个 1 1 1 2 2 2 ⋯ \cdots N N N的排列

输出描述:

T o n n n n y Tonnnny Tonnnny满意的最大天数,取余 1 0 N 10^N 10N

样例:

样例输入1:

5
1 2 3 4 5

样例输出1:

1

样例输入2:

6
2 3 4 5 6 1

样例输出2:

6

思路:

为啥牛客多校又出置换,这是牛客多校的特色嘛…
咳咳,一看到这道题,我就想到了多校第二场的J题,这题不就是那题的翻版嘛??????
本题就是置换群的一个应用,先求出所给序列的所有环的个数,然后求出环的周期数,题目要我们求出 1 ∼ n 1\sim n 1n的原数列经过多少次变换后会变回原数列,所以只要求出所有环的周期数的最小公倍数就可以了。
那么问题来了,这个数据范围的 l c m lcm lcm求出来可能会爆 l o n g l o n g longlong longlong ! ! !所以本题还要使用高精度乘法来求解。
任意一对数,它们如果有质因子相同,那么根据 l c m = a ∗ b / g c d lcm=a∗b/gcd lcm=ab/gcd可知,它会将公共的部分除掉,相当于对于每个质因子的个数求个 m a x max max即可。比如有质数 p r pr pr a a a= p r 3 pr^3 pr3∗… b b b= p r 5 pr^5 pr5∗… ,则它们的公共部分是 p r 3 pr^ 3 pr3,相乘之后有 p r 8 pr^ 8 pr8,除掉后有 p r 5 pr^ 5 pr5也就是 p r m a x ( 3 , 5 ) pr^{max(3,5)} prmax(3,5)。这样就可以避免高精度除法,只需要用高精乘低精就可以 A C AC AC
题目所说的取余操作嘛…根本就不会那么大,放出来打酱油的…

AC Code:

#include
using namespace std;
const int MAXN=1e5+5;
int n,len=1,w,cnt;
int a[MAXN],v[MAXN],b[MAXN],pr[MAXN],pri[MAXN],ans[MAXN]={0,1};
void mul(int x)
{
    for(int i=1;i<=len;i++) ans[i]*=x;
    for(int i=1;i<len;i++) if(ans[i]>9) ans[i+1]+=ans[i]/10,ans[i]%=10;
    while(len<n&&ans[len]>9) ans[len+1]+=ans[len]/10,ans[len++]%=10;
    ans[len+1]=0;
}//高精度乘法:高精乘低精
int main()
{
	for(int i=2;i<MAXN;i++)
		if(!pri[i])
			{
				for(int j=i*2;j<MAXN;j+=i)
					pri[j]=1;
				pr[++cnt]=i;
			}//素数筛
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		scanf("%d",a+i);
	for(int i=1;i<=n;i++)
		if(!v[i])
		{
			v[i]=b[++w]=1;
			for(int j=a[i];j!=i;j=a[j])
				v[j]=1,b[w]++;
		}//统计环的个数
	memset(pri,0,sizeof(pri));
	for(int i=1;i<=w;i++)
		for(int j=1,t=0;j<=cnt&&b[i]>1;j++)
		{
			while(b[i]%pr[j]==0){t++;b[i]/=pr[j];}
			pri[pr[j]]=max(pri[pr[j]],t);
			t=0;
		}
	for(int i=1;i<=cnt;i++)
		while(pri[pr[i]]--)
			mul(pr[i]);
	for(int i=len;i>=1;i--)
		printf("%d",ans[i]);
}

你可能感兴趣的:(2020牛客暑期多校训练营第五场Bogo Sort)