"Algorithm Competition · 300 Quick Questions" one question per day: "Approximate numbers"

" 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.


" Approximate numbers ", link: http://oj.ecustacm.cn/problem.php?id=1726

topic description

[Title Description] N! is a very large number, ask for the number of divisors of N!.
【Input format】 Enter a positive integer N, not exceeding 5*10^7.
[Output format] Output an integer to represent the answer, and the answer is the remainder of 1e9+7.
【Input sample】

5

【Example of output】

16

answer

  This is a classic question, using prime number sieve and prime factorization. According to the Fundamental Theorem of Arithmetic, any positive integer can be uniquely decomposed into the product of a finite number of prime numbers. In this question, first find all the prime numbers that can be decomposed by n!, and then count the number of divisors. The prime factor of n! only needs to be a prime number smaller than n.
[Key points] Euler sieve, prime factor decomposition.

C++ code

  The following code first uses Euler sieve euler_sieve() to find prime numbers smaller than n, and stores them in primes[], the number of which is cnt.
  Then in the for loop on line 23, count n! n!Divisor of n !
  Statistics also use the idea of ​​a prime number sieve. For example10! = 10 × 9 × 8 × 7 × 6 × 5 × 4 × 3 × 2 × 1 10! = 10 × 9 × 8 × 7 × 6 × 5 × 4 × 3 × 2 × 110!=10×9×8×7×6×5×4×3×2×1 , the first prime number is 2,10 ! 10!How many 2s are there in the factors of 10 !? Calculate like this: 10/2 = 5, 10/4 = 2, 10/8 = 1, a total of 5+2+1=8. Why?
  Swipe once in multiples of 2, that is, 2, 4, 6, 8, 10, a total of 5; then swipe in multiples of 4, that is, 4, 8, a total of 2; and then swipe in multiples of 8, that is, 8, a total of 1. In this way, the factors of 2 have been wiped out, and there are 5+2+1 = 8 2s in total.
  Note that the space limit for this question is 256M. The bool vis[N] on line 7 uses 50M, and the int primes[N/10] on line 8 uses 4×5M=20M. If line 8 is written as int primes[N], the total space may exceed 256M.

#include <bits/stdc++.h>
using namespace std;
const int N=5e7 + 10;
typedef long long ll;
ll mod = 1e9+7;
int cnt;                 //n以内素数的个数
bool vis[N];             //记录是否被筛
int primes[N/10];         //存素数。除以10可以省空间。1000万以内的素数不到100万个。
void euler_sieve(int n){
    
      //欧拉筛
    for(int i=2;i<=n;i++)    {
    
    
        if(!vis[i]) primes[cnt++]=i;
        for(int j=0; j<cnt; j++){
    
    
            if(i*primes[j]>n) break;
            vis[primes[j]*i] = true;
            if(i%primes[j]==0) break;
        }
    }
}
int main(){
    
    
    int n;  cin>>n;
    euler_sieve(n);
    ll ans = 1;
    for(int i=0;i<cnt;i++){
    
    
        ll p = primes[i], res=0;    //注意这里p是ll类型
        while(p<=n){
    
    
            res += n/p;             //res: 素数p在n!出现了res次
            p *= primes[i];
        }
        ans = ans*(res+1) % mod;
    }
    cout<<ans<<endl;
    return 0;
}

java code

import java.util.*;
public class Main {
    
    
    static final int N = 50000010;
    static int cnt;
    static boolean[] vis = new boolean[N];
    static int[] primes = new int[N/10];
    static long mod = 1000000007;
    static void euler_sieve(int n) {
    
    
        for (int i = 2; i <= n; i++) {
    
    
            if (!vis[i]) primes[cnt++] = i; 
            for (int j = 0; j < cnt && (long)i * primes[j] <= n; j++) {
    
    
                vis[i * primes[j]] = true;
                if (i % primes[j] == 0)  break;              
            }
        }
    }
    public static void main(String[] args) {
    
    
        Scanner scan = new Scanner(System.in);
        int n = scan.nextInt();
        euler_sieve(n);
        long ans = 1;
        for (int i = 0; i < cnt; i++) {
    
    
            long p = primes[i], res = 0;
            while (p <= n) {
    
    
                res += n / p;
                p *= primes[i];
            }
            ans = ans * (res + 1) % mod;
        }
        System.out.println(ans);
    }
}

Python code

  After submitting the following python code, it displays "Memory Exceeded". And the calculation time is too long. Such a topic is not suitable for implementation in Python.

N = 50000010
cnt = 0
vis = [False] * N      #print(sys.getsizeof(vis))打印vis占用的内存是400M
primes = [0] * (N//10)
mod = 1000000007
def euler_sieve(n):
    global cnt
    for i in range(2, n + 1):
        if not vis[i]:
            primes[cnt] = i
            cnt += 1
        for j in range(cnt):
            if i * primes[j] > n:  break
            vis[i * primes[j]] = True
            if i % primes[j] == 0:  break

n = int(input())
euler_sieve(n)
ans = 1
for i in range(cnt):
        p = primes[i]
        res = 0
        while p <= n:
            res += n // p
            p *= primes[i]
        ans = ans * (res + 1) % mod
print(ans)

Guess you like

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