把
a
i
a_i
ai 进行素因子分解,,其中一部分的乘积作为
d
1
d_1
d1, 另一部分的乘积作为
d
2
d_2
d2。
官方题解的证明:假设分解为
{
p
1
,
p
2
,
p
3
,
.
.
.
p
k
−
1
,
p
k
}
\{ p_1, p_2, p_3,...p_{k-1},p_k \}
{p1,p2,p3,...pk−1,pk},其中
d
1
=
p
1
⋅
p
2
⋅
p
3
⋅
.
.
.
p
x
,
d
2
=
p
x
+
1
⋅
.
.
.
⋅
p
k
d_1 = p_1 · p_2· p_3·...p_x, \ d_2 = p_{x+1}·...·p_k
d1=p1⋅p2⋅p3⋅...px, d2=px+1⋅...⋅pk,假设此时
gcd
(
d
1
+
d
2
,
a
i
)
≠
1
\gcd(\ d_1+d_2,\ a_i\ )\ \ne1
gcd( d1+d2, ai ) =1,那么必然存在一个(素)数
p
r
i
m
e
prime
prime ( gcd 的某个素因子 ),满足
(
d
1
+
d
2
)
%
p
r
i
m
e
=
0
)
(d_1+d_2)\%prime=0)
(d1+d2)%prime=0) 且
a
i
%
p
r
i
m
e
=
0
a_i \% prime = 0
ai%prime=0 ,这个素数
p
r
i
m
e
prime
prime 必然也是
a
i
a_i
ai 的素因子,而
a
i
a_i
ai 的素因子,一部分分给了
d
1
d_1
d1, 一部分分给了
d
2
d_2
d2。假设分给了
d
1
d_1
d1 ,肯定有
d
1
%
p
r
i
m
e
=
0
,
d
2
%
p
r
i
m
e
≠
0
d_1\%prime=0,\ d_2\%prime \ \ne 0
d1%prime=0, d2%prime =0,那么
(
d
1
+
d
2
)
%
p
r
i
m
e
=
d
1
%
p
r
i
m
e
+
d
2
%
p
r
i
m
e
≠
0
(d_1+d_2)\%prime = d_1\%prime+ d_2\%prime \ \ne 0
(d1+d2)%prime=d1%prime+d2%prime =0,不符合原假设。
然后学会了怎么快速进行素因子分解:先通过欧拉筛或线性筛可以得到每个数的最小的素因子,记作 m i n P r i m e [ x ] minPrime[x] minPrime[x]:
void prework() {
for(int i=2;i<=N;i++) minPrime[i] = INF;
for(int i=2;i<=N;i++) {
if( minPrime[i] == INF ) {
for(int j=i;j<=N;j+=i){
minPrime[j] = min( minPrime[j], i );
}
}
}
}
分解素因子就可以写成这样:(我这里是多个相同的只算一个)
int getPrimes(int x) {
int tot = 0;
while( x > 1 ) {
int p = minPrime[x];
vec[tot++] = p;
while( x%p == 0 ) {
x /= p;
}
}
return tot;
}
main:
int main()
{
prework();
int T = 1;
// scanf("%d",&T);
while(T--)
{
int n,m;
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",a+i);
for(int i=1;i<=n;i++) {
int tot = getPrimes(a[i]);
if( tot == 1 )d1[i] = d2[i] = -1;
else {
d1[i] = vec[0];
// d2[i] = vec[1];
d2[i] = 1;
for(int j=1;j<tot;j++) d2[i] *= vec[j];
}
}
for(int i=1;i<=n;i++) printf("%d ",d1[i]); NL;
for(int i=1;i<=n;i++) printf("%d ",d2[i]); NL;
}
}