"Algorithm Competition · 300 Quick Questions" one question per day: "Number of Prime Factors"

" Algorithm Competition: 300 Quick Questions " will be published in 2024, and it is an auxiliary workbook for "Algorithm Competition" .
All questions are placed in the self-built OJ New Online Judge .
The codes are provided in C/C++, Java, and Python. The topics are mainly low-to-medium level, suitable for beginners and advanced.


" Number of prime factors ", link: http://oj.ecustacm.cn/problem.php?id=1780

topic description

[Title description] Given n numbers, you can choose some numbers and multiply them together. After multiplication, you will get a new number x. The fraction of x is equal to the number of different prime factors of x.
  Please calculate the sum of the x-scores for all selected number schemes. The answer is modulo 1000000007.
[Input format] Input the first line as a positive integer n.
  The second line contains n positive integers ai. (1≤n≤200000, 1≤ai≤1000000).
[Output Format] Output an integer to represent the answer.
【Input sample】

3
6 1 2

【Example of output】

10

answer

  Example {6, 1, 2} has 3 numbers, 3 numbers have 2 3 = 8 2^3 = 823=8 combinations, the numbers in each combination are multiplied to get { ∅ \emptyset , 1, 2, 6, 1×2, 1×6, 2×6, 1×2×6} = { ∅ \emptyset , 1, 2, 2×3, 2, 2×3, 2×2×3, 2×2×3}, their number of prime factors is {0, 0, 1, 2, 1, 2, 2, 2}, and the sum is 10. ∅ \emptyset represents the empty set.
  The simple way is to calculate the prime factor of each number separately, calculate its score, and then count the total score of n numbers, but this simple way will time out. The prime factorization of a number a is the trial divisionof 2 22 ~n \sqrt{n}n All prime numbers in ; do prime factorization for n numbers, the total complexity is nan\sqrt{a}na ,time out.
  In this question, the scores of each number are not calculated separately, but are calculated together. Multiply any number from n numbers, a total of 2 n 2^n2n kinds of combinations. If a prime number appears once in a combination, add 1 to the answer; counting the total number of times all prime numbers appear in all combinations is the answer. How many combinations can a prime number appear in? Let i be a factor of k numbers, then it is in2 n − 2 n − k 2^n-2^{nk}2n2appear in n k combinations. For example, in the sample {6, 1, 2}, the prime number 2 is a factor of the two numbers {6, 2}, and in {2, 6, 1×2, 1×6, 2×6, 1×2×6}, 2 3 − 2 3 − 2 = 6 2^3-2^{3-2} =623232=Appears in 6 combinations; 3 is a factor of {6}, in {6, 1×6, 2×6, 1×2×6} this 2 3 − 2 3 − 1 = 4 2^3-2^{3-1} = 423231=Appears in 4 combinations. The answer is 6+4=10.
  The problem-solving steps of this question are: use the prime number sieve to get all the prime numbers; count the number k of each prime number in n numbers, use2 n − 2 n − k 2^n-2^{nk}2n2n k calculates its score in all combinations. While doing the prime number sieve, count the number of times the prime number appears, the total amount of calculation is equivalent to only doing the prime number sieve once, the complexityO ( alog 2 log 2 a ) O(alog_2log_2a)Or ( a l o g2log2a) a ≤ 1000000 a≤1000000 a1000000 .
【Key Points】Master prime factorization.

C++ code

  Calculate 2 n 2^n2The pow() library function cannot be used for n , because n is too large, and pow() cannot perform large power calculations; let alone use bitwise operations 2<<n directly. The code calculates 2 n 2^nwith fastpow()2n . The first MOD in line 30 cannot be missing, because fastpow() returns the result of the modulus, so fastpow(2, n) - fastpow(2, n - k) may be negative, and MOD needs to be added to ensure it is positive.

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6 + 10;
const int MOD = 1e9 + 7;
int cnt[N];
bool not_prime[N];
ll fastpow(ll a, ll n){
    
             //快速幂,计算a^n,并取模
    ll ans = 1;
    while(n){
    
    
        if(n & 1)  ans = ans * a % MOD;
        a = a * a % MOD;
        n >>= 1;
    }
    return ans;
}
int main(){
    
    
    int n;  cin >> n;
    for(int i = 1; i <= n; i++) {
    
    
        int a;  scanf("%d",&a);
        cnt[a]++;
    }
    ll ans = 0;
    for(int i = 2; i < N; i++)                     //素数筛
        if(!not_prime[i]){
    
                              //i是质数
            ll k = cnt[i];                          //统计质数i出现的次数k
            for(int j = 2*i; j < N; j += i)        //把i的倍数筛掉,留下的是素数
                k += cnt[j], not_prime[j] = true;   //统计质数i出现的次数k
            if(k)
                ans = (ans + fastpow(2, n) - fastpow(2, n-k) + MOD) % MOD;  //质数i的得分是2^n-2^(n-k)
        }
    cout<<ans<<endl;
    return 0;
}

java code

import java.util.Scanner;
public class Main {
    
    
    static final int N = 1000010;
    static final int MOD = 1000000007;
    static int[] cnt = new int[N];
    static boolean[] notPrime = new boolean[N];
    public static void main(String[] args) {
    
    
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        for (int i = 0; i < n; i++) {
    
    
            int a = sc.nextInt();
            cnt[a]++;
        }
        long ans = 0;
        for (int i = 2; i < N; i++) {
    
                      //素数筛
            if (!notPrime[i]) {
    
                            //i是质数
                long k = cnt[i];                       //统计质数i出现的次数k
                for (int j = 2 * i; j < N; j += i) {
    
       //把i的倍数筛掉,留下的是素数
                    k += cnt[j];                       //统计质数i出现的次数k
                    notPrime[j] = true;
                }
                if (k != 0) 
                    ans = (ans+fastPow(2,n) - fastPow(2,n-k) + MOD) % MOD; //质数i的得分是2^n-2^(n-k)
            }
        }
        System.out.println(ans);
        sc.close();
    }
    static long fastPow(long a, long n) {
    
                  //快速幂,计算a^n,并取模
        long ans = 1;
        while (n > 0) {
    
    
            if ((n & 1) == 1)  ans = ans * a % MOD;

            a = a * a % MOD;
            n >>= 1;
        }
        return ans;
    }
}

Python code

N = 1000010
MOD = 1000000007
cnt = [0] * N
not_prime = [False] * N
def fastpow(a, n):                 #快速幂,计算a^n,并取模
    ans = 1
    while n:
        if n & 1:  ans = ans * a % MOD
        a = a * a % MOD
        n >>= 1
    return ans
n = int(input())
a = list(map(int, input().split()))
for i in a: cnt[i] += 1
ans = 0
for i in range(2, N):              #素数筛
    if not not_prime[i]:           #i是质数
        k = cnt[i]                 #统计质数i出现的次数k
        for j in range(2 * i, N, i):       #把i的倍数筛掉,留下的是素数
            k += cnt[j]                    #统计质数i出现的次数k
            not_prime[j] = True
        if k:
            ans = (ans + fastpow(2, n) - fastpow(2, n - k) + MOD) % MOD   #质数i的得分是2^n-2^(n-k)
print(ans)

Guess you like

Origin blog.csdn.net/weixin_43914593/article/details/131750902