CF1366D

Two Divisors

题意:

n个1e7内的数,求每个数的两个因子 d 1 、 d 2 d_1、 d_2 d1d2,满足 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 d1d2不存在,那么输出-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 d10 mod pi,但 d 2 ≢ 0   m o d   p i d_2\not\equiv0 \ mod \ p_i d20 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+d20+d2d20 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 d1d2一定存在;如果只有一个质因子,那么不存在

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

猜你喜欢

转载自blog.csdn.net/weixin_44049850/article/details/106770163