Two Divisors
题意:
n个1e7内的数,求每个数的两个因子 d 1 、 d 2 d_1、 d_2 d1、d2,满足 g c d ( d 1 + d 2 , a [ i ] ) = 1 gcd(d_1+d_2, a[i])=1 gcd(d1+d2,a[i])=1. 如果 d 1 、 d 2 d_1、 d_2 d1、d2不存在,那么输出-1
以下:
对
a
[
i
]
a[i]
a[i]进行质因数分解:
a
[
i
]
=
p
1
s
1
p
2
s
2
.
.
.
p
k
s
k
a[i]=p_1^{s_1}p_2^{s_2}...p_k^{s_k}
a[i]=p1s1p2s2...pksk
我们把
p
1
,
p
2
,
.
.
.
,
p
k
p_1,p_2,...,p_k
p1,p2,...,pk分成两个集合
{
p
1
,
p
2
,
.
.
.
,
p
x
}
\{p_1,p_2,...,p_x\}
{p1,p2,...,px}和
{
p
x
+
1
,
p
x
+
2
,
.
.
.
,
p
k
}
\{p_{x+1},p_{x+2},...,p_k\}
{px+1,px+2,...,pk}
使
d
1
=
p
1
p
2
.
.
.
p
x
d_1=p_1p_2...p_x
d1=p1p2...px,
d
2
=
p
x
+
1
p
x
+
2
.
.
.
p
k
d_2=p_{x+1}p_{x+2}...p_k
d2=px+1px+2...pk
证明:
我们任意取集合
{
p
1
,
p
2
,
.
.
.
,
p
x
}
\{p_1,p_2,...,p_x\}
{p1,p2,...,px}中一个
p
i
p_i
pi,明显有:
a
[
i
]
≡
0
m
o
d
p
i
a[i]\equiv0 \ mod \ p_i
a[i]≡0 mod pi,
d
1
≡
0
m
o
d
p
i
d_1\equiv0 \ mod \ p_i
d1≡0 mod pi,但
d
2
≢
0
m
o
d
p
i
d_2\not\equiv0 \ mod \ p_i
d2≡0 mod pi
所以
d
1
+
d
2
≡
0
+
d
2
≡
d
2
≢
0
m
o
d
p
i
d_1+d_2\equiv0+d_2\equiv d_2\not\equiv0 \ mod \ p_i
d1+d2≡0+d2≡d2≡0 mod pi
所以
g
c
d
(
d
1
+
d
2
,
a
[
i
]
)
=
1
gcd(d_1+d_2, a[i])=1
gcd(d1+d2,a[i])=1
所以只要一个数有两个及以上的质因子(即k>=2),那么一定 d 1 、 d 2 d_1、 d_2 d1、d2一定存在;如果只有一个质因子,那么不存在
Anser
我们求出每个
a
[
i
]
a[i]
a[i]的最小质因子
d
1
d_1
d1,然后将该最小质因子除去,得到与
d
1
d_1
d1互质的
d
2
d_2
d2
:最小质因子
D
i
v
M
i
n
DivMin
DivMin可以在线性筛筛素数的时候得到
Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxN = 500005;
const int N = 10000001;
bool vis[N];
int prime[700000], cnt;
int DivMin[N];
void GetPrime()
{
vis[0] = vis[1] = true;
for(int i = 2; i < N; ++ i ) {
if(!vis[i]) {
prime[++ cnt] = i;
DivMin[i] = i;
}
for(int j = 1; j <= cnt; ++ j ) {
if(i * prime[j] >= N) break;
vis[i * prime[j]] = true;
DivMin[i * prime[j]] = prime[j];
if(i % prime[j] == 0) break;
}
}
}
int n, a[maxN];
int fir[maxN], sec[maxN];
void Div(int x, int p) {
if(!vis[x]) {
fir[p] = sec[p] = -1;
return ;
}
fir[p] = DivMin[x];
sec[p] = x / fir[p];
while(sec[p] % fir[p] == 0) {
sec[p] /= fir[p];
}
if(sec[p] == 1)
fir[p] = sec[p] = -1;
}
int main() {
GetPrime();
cin >> n;
for(int i = 0; i < n; ++ i )
cin >> a[i];
for(int i = 0; i < n; ++ i )
{
Div(a[i], i);
}
for(int i = 0; i < n; ++ i ) {
cout << fir[i] << " \n"[i == n - 1];
}
for(int i = 0; i < n; ++ i ) {
cout << sec[i] << " \n"[i == n - 1];
}
return 0;
}
/*
5
10000000 9999999 9999998 9999997 9999996
*/