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的代码:
老师说,函数
s
h
u
f
f
l
e
shuffle
shuffle是等概率地随机排列长度为
N
N
N的数组
a
a
a,这个算法的期望复杂度为
O
(
n
⋅
n
!
)
O(n⋅n!)
O(n⋅n!)。
但是,
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如此认为。
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
1∼n的原数列经过多少次变换后会变回原数列,所以只要求出所有环的周期数的最小公倍数就可以了。
那么问题来了,这个数据范围的
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=a∗b/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<bits/stdc++.h>
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]);
}