Hướng dẫn cho Mặt nạ nguyên tố
Chỉ sử dụng khi thực sự cần thiết như một cách tôn trọng tác giả và người viết hướng dẫn này.
Chép code từ bài hướng dẫn để nộp bài là hành vi có thể dẫn đến khóa tài khoản.
Chép code từ bài hướng dẫn để nộp bài là hành vi có thể dẫn đến khóa tài khoản.
Authors:
Hướng dẫn giải: Mặt nạ nguyên tố
Phân tích
Với mỗi số \( n \), gọi các ước nguyên tố phân biệt là:
\( p_1, p_2, ..., p_k \), với \( k \ge 2 \)
Đặt:
\[
S = p_1 + p_2 + \cdots + p_k
\]
\[
P = p_1 \cdot p_2 \cdots p_k
\]
Điều kiện:
- \( P \mod S = 0 \)
- \( Q = \frac{P}{S} \) là số nguyên tố
Nhận xét
Chỉ xét prime phân biệt, không quan tâm số mũ
Sub 1 (25%)
Ý tưởng
- Duyệt từng số
- Phân tích thừa số bằng chia thử
- Lấy tập prime
- Tính \( S, P \)
Code C++
C++
#include <bits/stdc++.h>
using namespace std;
bool isPrime(int x){
if(x < 2) return false;
for(int i = 2; i * i <= x; i++)
if(x % i == 0) return false;
return true;
}
int main(){
int T; cin >> T;
while(T--){
int L, R; cin >> L >> R;
int ans = 0;
for(int n = L; n <= R; n++){
int x = n;
set<int> primes;
for(int i = 2; i * i <= x; i++){
if(x % i == 0){
primes.insert(i);
while(x % i == 0) x /= i;
}
}
if(x > 1) primes.insert(x);
if(primes.size() < 2) continue;
long long P = 1;
int S = 0;
for(int p : primes){
P *= p;
S += p;
}
if(P % S == 0){
int Q = P / S;
if(isPrime(Q)) ans++;
}
}
cout << ans << '\n';
}
}
Sub 2 (25%)
Ý tưởng
Dùng SPF để phân tích nhanh mỗi số
Code C++
C++
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 5000000;
int spf[MAXN + 1];
void sieve(){
for(int i = 1; i <= MAXN; i++) spf[i] = i;
for(int i = 2; i * i <= MAXN; i++){
if(spf[i] == i){
for(int j = i * i; j <= MAXN; j += i)
if(spf[j] == j) spf[j] = i;
}
}
}
bool isPrime(int x){
if(x < 2) return false;
for(int i = 2; i * i <= x; i++)
if(x % i == 0) return false;
return true;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
sieve();
int T; cin >> T;
while(T--){
int L, R; cin >> L >> R;
int ans = 0;
for(int n = L; n <= R; n++){
int x = n;
set<int> primes;
while(x > 1){
primes.insert(spf[x]);
x /= spf[x];
}
if(primes.size() < 2) continue;
long long P = 1;
int S = 0;
for(int p : primes){
P *= p;
S += p;
}
if(P % S == 0){
int Q = P / S;
if(isPrime(Q)) ans++;
}
}
cout << ans << '\n';
}
}
Sub 3 (25%)
Ý tưởng
Precompute tất cả số hợp lệ và dùng prefix sum
Code Python
Python
MAXN = 100000
spf = list(range(MAXN + 1))
for i in range(2, int(MAXN**0.5) + 1):
if spf[i] == i:
for j in range(i*i, MAXN+1, i):
if spf[j] == j:
spf[j] = i
is_prime = [True]*(MAXN+1)
is_prime[0] = is_prime[1] = False
for i in range(2, int(MAXN**0.5)+1):
if is_prime[i]:
for j in range(i*i, MAXN+1, i):
is_prime[j] = False
pref = [0]*(MAXN+1)
for n in range(1, MAXN+1):
x = n
primes = set()
while x > 1:
primes.add(spf[x])
x //= spf[x]
ok = False
if len(primes) >= 2:
P = 1
S = 0
for p in primes:
P *= p
S += p
if P % S == 0:
Q = P // S
if Q <= MAXN and is_prime[Q]:
ok = True
pref[n] = pref[n-1] + (1 if ok else 0)
import sys
input = sys.stdin.readline
T = int(input())
for _ in range(T):
L, R = map(int, input().split())
print(pref[R] - pref[L-1])
Sub 4 (100%)
Ý tưởng
Sieve nâng cao: đẩy thông tin từ prime xuống bội
Code C++
C++#include <bits/stdc++.h>
using namespace std;
const int MAX_VAL = 5000000;
int sum_primes[MAX_VAL + 1];
long long prod_primes[MAX_VAL + 1];
int count_primes[MAX_VAL + 1];
bool is_prime[MAX_VAL + 1];
int prefix_sum[MAX_VAL + 1];
void precompute() {
fill(is_prime + 2, is_prime + MAX_VAL + 1, true);
for (int i = 1; i <= MAX_VAL; ++i)
prod_primes[i] = 1;
for (int i = 2; i <= MAX_VAL; ++i) {
if (is_prime[i]) {
for (int j = i; j <= MAX_VAL; j += i) {
if (j > i) is_prime[j] = false;
sum_primes[j] += i;
count_primes[j]++;
if (prod_primes[j] != -1) {
if (prod_primes[j] > MAX_VAL / i + 1)
prod_primes[j] = -1;
else
prod_primes[j] *= i;
}
}
}
}
for (int n = 1; n <= MAX_VAL; ++n) {
bool ok = false;
if (count_primes[n] >= 2) {
int S = sum_primes[n];
long long P = prod_primes[n];
if (P != -1 && P % S == 0) {
int Q = P / S;
if (Q <= MAX_VAL && is_prime[Q]) {
ok = true;
}
}
}
prefix_sum[n] = prefix_sum[n - 1] + (ok ? 1 : 0);
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
precompute();
int T;
cin >> T;
while (T--) {
int L, R;
cin >> L >> R;
cout << prefix_sum[R] - prefix_sum[L - 1] << '\n';
}
}
#include <bits/stdc++.h>
using namespace std;
const int MAX_VAL = 5000000;
int sum_primes[MAX_VAL + 1];
long long prod_primes[MAX_VAL + 1];
int count_primes[MAX_VAL + 1];
bool is_prime[MAX_VAL + 1];
int prefix_sum[MAX_VAL + 1];
void precompute() {
fill(is_prime + 2, is_prime + MAX_VAL + 1, true);
for (int i = 1; i <= MAX_VAL; ++i)
prod_primes[i] = 1;
for (int i = 2; i <= MAX_VAL; ++i) {
if (is_prime[i]) {
for (int j = i; j <= MAX_VAL; j += i) {
if (j > i) is_prime[j] = false;
sum_primes[j] += i;
count_primes[j]++;
if (prod_primes[j] != -1) {
if (prod_primes[j] > MAX_VAL / i + 1)
prod_primes[j] = -1;
else
prod_primes[j] *= i;
}
}
}
}
for (int n = 1; n <= MAX_VAL; ++n) {
bool ok = false;
if (count_primes[n] >= 2) {
int S = sum_primes[n];
long long P = prod_primes[n];
if (P != -1 && P % S == 0) {
int Q = P / S;
if (Q <= MAX_VAL && is_prime[Q]) {
ok = true;
}
}
}
prefix_sum[n] = prefix_sum[n - 1] + (ok ? 1 : 0);
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
precompute();
int T;
cin >> T;
while (T--) {
int L, R;
cin >> L >> R;
cout << prefix_sum[R] - prefix_sum[L - 1] << '\n';
}
}
Code Python (Sub 4 - Full AC)
Pythonimport sys
input = sys.stdin.readline
MAX = 5000000
sum_primes = [0] * (MAX + 1)
prod_primes = [1] * (MAX + 1)
count_primes = [0] * (MAX + 1)
is_prime = [True] * (MAX + 1)
prefix_sum = [0] * (MAX + 1)
is_prime[0] = is_prime[1] = False
# sieve + cập nhật
for i in range(2, MAX + 1):
if is_prime[i]:
for j in range(i, MAX + 1, i):
if j > i:
is_prime[j] = False
sum_primes[j] += i
count_primes[j] += 1
if prod_primes[j] != -1:
if prod_primes[j] > MAX // i + 1:
prod_primes[j] = -1
else:
prod_primes[j] *= i
# prefix
for n in range(1, MAX + 1):
ok = False
if count_primes[n] >= 2:
S = sum_primes[n]
P = prod_primes[n]
if P != -1 and P % S == 0:
Q = P // S
if Q <= MAX and is_prime[Q]:
ok = True
prefix_sum[n] = prefix_sum[n - 1] + (1 if ok else 0)
# query
T = int(input())
for _ in range(T):
L, R = map(int, input().split())
print(prefix_sum[R] - prefix_sum[L - 1])
import sys
input = sys.stdin.readline
MAX = 5000000
sum_primes = [0] * (MAX + 1)
prod_primes = [1] * (MAX + 1)
count_primes = [0] * (MAX + 1)
is_prime = [True] * (MAX + 1)
prefix_sum = [0] * (MAX + 1)
is_prime[0] = is_prime[1] = False
# sieve + cập nhật
for i in range(2, MAX + 1):
if is_prime[i]:
for j in range(i, MAX + 1, i):
if j > i:
is_prime[j] = False
sum_primes[j] += i
count_primes[j] += 1
if prod_primes[j] != -1:
if prod_primes[j] > MAX // i + 1:
prod_primes[j] = -1
else:
prod_primes[j] *= i
# prefix
for n in range(1, MAX + 1):
ok = False
if count_primes[n] >= 2:
S = sum_primes[n]
P = prod_primes[n]
if P != -1 and P % S == 0:
Q = P // S
if Q <= MAX and is_prime[Q]:
ok = True
prefix_sum[n] = prefix_sum[n - 1] + (1 if ok else 0)
# query
T = int(input())
for _ in range(T):
L, R = map(int, input().split())
print(prefix_sum[R] - prefix_sum[L - 1])
Code Java (Sub 4)
Java
import java.util.*;
public class Main {
static final int MAX = 5000000;
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int[] sum = new int[MAX+1];
long[] prod = new long[MAX+1];
int[] cnt = new int[MAX+1];
boolean[] isPrime = new boolean[MAX+1];
int[] pref = new int[MAX+1];
Arrays.fill(isPrime, true);
isPrime[0] = isPrime[1] = false;
Arrays.fill(prod, 1);
for(int i=2;i<=MAX;i++){
if(isPrime[i]){
for(int j=i;j<=MAX;j+=i){
if(j>i) isPrime[j]=false;
sum[j]+=i;
cnt[j]++;
if(prod[j]!=-1){
if(prod[j] > MAX / i + 1) prod[j] = -1;
else prod[j]*=i;
}
}
}
}
for(int n=1;n<=MAX;n++){
boolean ok=false;
if(cnt[n]>=2){
int S=sum[n];
long P=prod[n];
if(P!=-1 && P%S==0){
int Q=(int)(P/S);
if(Q<=MAX && isPrime[Q]) ok=true;
}
}
pref[n]=pref[n-1]+(ok?1:0);
}
int T=sc.nextInt();
while(T-- > 0){
int L=sc.nextInt(), R=sc.nextInt();
System.out.println(pref[R]-pref[L-1]);
}
}
}
Bình luận