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
*/