Educational Codeforces Round 89 D. Two Divisors (数论+gcd性质)
题目链接
题意:
给\(n\)个数,对于每个数找到它的两个因子\(d_1、d_2\)使得\(gcd(d_1+d_2,a_i)=1\),若不存在则输出\(-1\)。
思路:
由唯一分解定理得:\(a_i={p_1}^{k_1}*{p_2}^{k_2}...{p_m}^{k_m}\)。
\(gcd\)性质:\(gcd(a,b)=gcd(a+b,b)\),若\(gcd(a,c)=1\),则\(gcd(a,b)=gcd(a,bc)\)。
令\(d_1={p_1}^{k_1},d_2={p_2}^{k_2}...{p_m}^{k_m}\),所以\(gcd(d_1,d_2)=1\)。
故\(gcd(d_1,d_2)=gcd(d_1+d_2,d_1)=gcd(d_1+d_2,d_2)=1\)
\(\Rightarrow\) \(gcd(d_1+d_2,d_1*d_2)=gcd(d_1+d_2,a_i)=1\)。
当\(a_i\)有两个以上的素数因子时,则必然可以找到\(d_1,d_2\);可以由素数筛\(O(n)\)判断一个数是否为素数且找到其一个素数因子。
- 素数筛的注意点:
内层循环判断:
for(int j = 1; j <= tot && 1ll * i * p[j] < maxn; j++) {
// 判断范围时一定是i * p[j] < maxn,而不是p[j] < maxn/i
// 例如:2 * 4 < 9,但 2 = 9/4
vis[i * p[j]] = 0;
if(i % p[j] == 0)break;
}
code:
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <algorithm>
#include <cmath>
#define ll long long
const int maxn = 1e7 + 10;
using namespace std;
bool vis[maxn];
int p[maxn], a_p[maxn];
int ans[maxn][2], tot;
void getprime(){
memset(vis, 1, sizeof vis);
for(int i = 2; i < maxn; i ++){
if(vis[i])p[++ tot] = i;
for(int j = 1; j <= tot && 1ll * i * p[j] < maxn; j ++){
vis[i * p[j]] = 0;
a_p[i * p[j]] = p[j];
if(i % p[j] == 0)break;
}
}
}
int main(){
getprime();
int n; scanf("%d", &n);
for(int i = 1, a; i <= n; i++) {
scanf("%d", &a);
if(vis[a])ans[i][0] = ans[i][1] = -1;
else{
int p = a_p[a], b = 1;
while(a % p == 0) a /= p, b *= p;
if(a != 1)ans[i][0] = b, ans[i][1] = a;
else ans[i][0] = ans[i][1] = -1;
}
}
for(int i = 1; i <= n; i ++)printf("%d ", ans[i][0]);
puts("");
for(int i = 1; i <= n; i++)printf("%d ", ans[i][1]);
return 0;
}

浙公网安备 33010602011771号