Introduction to Niuke algorithm Mathematics: 1001-1006 prime numbers

Posted by stonefish on Mon, 14 Feb 2022 09:07:33 +0100

0x00 topic source

Special topics in Mathematics

0x10 Tag

Mathematics, prime, Euler sieve

0x20 1001 prime judgment

Give a number x, judge whether it is a prime number, and output all its prime factors.

0x21 prime sieve (Euler sieve)

The boards are as follows:

bool isnp[MAXN];
vector<int> primes;
void init(int n)
{
    for (int i = 2; i <= n; i++)
    {
        if (!isnp[i])
            primes.push_back(i);
        for (int p : primes)
        {
            if (p * i > n)
                break;
            isnp[p * i] = 1;
            if (i % p == 0)
                break;
        }
    }
}

A simple method of screening prime numbers, which uses prime numbers to screen composite numbers from small to large. But the problem is that the sum will be sifted out by more than two prime numbers. For example, 30 will be repeatedly sifted out by 2, 3 and 5.

So we introduce Euler sieve, and let's simulate the following screening process

Hypothetical array A = [ 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 , 16 , 17 , 18 , 19 , 20 ] A=[2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20] A=[2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20] prime number table at this time P = [ ] P=[] P=[];

Put the number that is not traversed into the prime table for the first time, A P = [ 2 ] P=[2] P=[2];
Select 2, multiply 2 with all numbers in the prime number table (only 2), and sift out the multiplication result (4)
array A = [ 2 , 3 , 4 ∗ , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 , 16 , 17 , 18 , 19 , 20 ] A=[2,3,4* ,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20] A=[2,3,4∗,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
The * after the number indicates that it has been screened out

Traverse A for the second time, and put the first number not screened into the prime number table P = [ 2 , 3 ] P=[2,3] P=[2,3];
Select 3, multiply 3 by all numbers in the prime number table (2,3), and sift out the multiplication results (6,9)
array A = [ 2 , 3 , 4 ∗ , 5 , 6 ∗ , 7 , 8 , 9 ∗ , 10 , 11 , 12 , 13 , 14 , 15 , 16 , 17 , 18 , 19 , 20 ] A=[2,3,4* ,5,6*,7,8,9*,10,11,12,13,14,15,16,17,18,19,20] A=[2,3,4∗,5,6∗,7,8,9∗,10,11,12,13,14,15,16,17,18,19,20]

After traversing A for the third time, it is found that 4 has been screened out
Select 4, multiply 4 by all numbers in the prime number table (2,3), and sift out the multiplication results (8,12)??

The most important difference of Eulerian sieve is here, if we traverse the prime table and get p p p discovery p p p to divide the number we choose, we should stop sieving, because the core of Euler sieve is to use the smallest quality factor to sieve the combined number. In this example, 12 should be sifted out by 2 (in 2 × 6 2\times 6 two × 6), so we only cross out 8, A = [ 2 , 3 , 4 ∗ , 5 , 6 ∗ , 7 , 8 ∗ , 9 ∗ , 10 , 11 , 12 , 13 , 14 , 15 , 16 , 17 , 18 , 19 , 20 ] A=[2,3,4* ,5,6*,7,8*,9*,10,11,12,13,14,15,16,17,18,19,20] A=[2,3,4∗,5,6∗,7,8∗,9∗,10,11,12,13,14,15,16,17,18,19,20]. if (i % p == 0) break; The simulation is to stop the screening process

Traverse A for the fourth time and put the first unfiltered number into the prime number table P = [ 2 , 3 , 5 ] P=[2,3,5] P=[2,3,5];
Select 5, multiply 5 by all numbers in the prime table (2,3), and sift out the multiplication results (10,15,25)
array A = [ 2 , 3 , 4 ∗ , 5 , 6 ∗ , 7 , 8 , 9 ∗ , 10 ∗ , 11 , 12 , 13 , 14 , 15 ∗ , 16 , 17 , 18 , 19 , 20 ] A=[2,3,4* ,5,6*,7,8,9*,10*,11,12,13,14,15*,16,17,18,19,20] A=[2,3,4∗,5,6∗,7,8,9∗,10∗,11,12,13,14,15∗,16,17,18,19,20]
...

0x22 O(sqrt(n)) judge prime

bool isP(long long n){
    if(n == 1) return 0;
    if(n == 2) return 1;
    if(!(n&1)) return 0;
    for(long long i = 3;i*i<=n;i+=2) if(!(n%i)) return 0;
    return 1;
}

0x22 O(logN) decomposition quality factor

vector<int> n_primes;
void dec(int n)
{
    n_primes.clear();
    while(n%2==0)
    {
        n_primes.push_back(2);
        n/=2;
    }
    for(int i=3;i<=sqrt(n*1.0);i+=2)
    {
        while(n%i==0)
        {
            n_primes.push_back(i);
            n/=i;
        }
    }
    if(n>2)
        n_primes.push_back(n);
}

The specific process is

  1. Divide by all factors in multiples of 2
  2. Enumerating integers with i as multiple and factor
  3. n itself is a prime

The first step is to optimize the complexity to O(logN)

0x23 set de duplication

	vector<int>v;
	set<int>s(v.begin(),v.end());
    v.assign(s.begin(),s.end());

0x20 1002 prime judgment

Now give a prime number that satisfies two points:
1. It only consists of 1-9, and each number appears only once, such as 13,231289.
2. The number of digits decreases or increases from high to low, such as 245987631.
Please judge whether the palindrome number of this prime number is a prime number (the palindrome number of 13 is 131127 and the palindrome number of 12721).

Simulate the construction of palindrome string and judge isP()

Damn it

for(ll i=2;i*i<=x;i++)

If it is not written as long, long will timeout instead of Wa

0x40 1004 prime distribution

Prime distribution function \ pi (n) π (n) represents the number of prime numbers less than or equal to n. For example \ pi (10)=4 π (10) = 4 (2,3,5,7 are prime numbers). This function involves many contents of higher number theory, even linked to Riemann conjecture. At present, many mathematicians are constantly exploring the mystery. The journey of a thousand miles begins with a single step. Now you begin to care about a problem: what is the distribution of prime numbers in the field of positive integers. To explore this problem, you need to calculate some values of \ pi (n) π (n).

Prime sieve template

0x50 1005 forsaken likes number theory

Forsaken has an interesting number theoretic function. For any number x, f(x) returns the minimum prime factor of X. If the number has no minimum prime factor, it returns 0.
Now, given any n, Forsaken wants to know ∑ i = 1 n \sum_{i = 1}^{n} The value of Σ i=1n.

Data range 1 ≤ n ≤ 3e7

At first, I had two ideas: one is that after typing the table, for each x, I traverse the whole prime number table to find its minimum prime factor (the first divisible prime number), but its time complexity is close O ( n 2 + n ) O(n^2+n) O(n2+n). In the other way, after the table is printed, each number decomposes the prime factor to find the smallest prime factor, with a complexity of O ( n l o g n + n ) O(nlogn+n) O(nlogn+n) . Will be 3 e 7 3e7 3e7 stuck.

The correct approach should be to record the minimum quality factor when typing the table, as shown in the following code:

void init(int n)
{
    for (int i = 2; i <= n; i++)
    {
        if (!isnp[i])
        {
            primes.push_back(i),ans+=i;
        }
            
        for (int p : primes)
        {
            if (p * i > n)
                break;
            isnp[p * i] = 1;
            ans+=p;
            if (i % p == 0)
                break;
        }
    }
}

The reason is that Euler sieve uses the smallest quality factor sieve to combine numbers. The time complexity is O ( n ) O(n) O(n), meet the problem design.

0x60 1006 beautiful number

Xiaohong defines a number as "beautiful number" if it meets the following conditions:

  1. The number is not prime.
  2. The number can be decomposed into the product of two prime numbers
  3. Input L and r, please output how many beautiful numbers there are in the [l,r] closed interval.

On the first line, enter a positive integer T, representing t queries
Two positive integers l and rr, separated by spaces.
1 ≤ t ≤ 1 0 5 1 \leq t \leq 10^5 1≤t≤105
1 ≤ l , r ≤ 1 0 8 1\le l,r\le 10^8 1≤l,r≤108

Time complexity of factor decomposition after table printing O ( T ( n + n l o g n ) ) O(T(n+nlogn)) O(T(n+nlogn)), obviously timeout (although 3S is given)
The positive solution of this problem should be to determine the beautiful number by typing the table respectively, and the number of query intervals can reduce the complexity to O ( 1 ) O(1) O(1), total complexity O ( T ( n ) ) O(T(n)) O(T(n)).

The code is as follows:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll MOD = 998244353;
const ll INF = 0x7fffffff;
#define f(i,a,b) for(int i = a;i < b;i++)
#define fd(i,a,b) for(int i = a;i > b;i--)
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define ret return
#define HACK freopen("test.in", "r", stdin);freopen("test.out", "w", stdout);
#define RT double rtime = 1.0 * clock() / CLOCKS_PER_SEC;cout<<"\nRuntime: "<<rtime<< " s.\n";
#define debug(x) cout<<"target is "<<x<<endl
#define debug_arr(x) for(auto e:x) cout<<e<<" ",cout<<endl;
#define LOCAL_JUDGE
#pragma GCC optimize(2)
namespace IO
{
    template<typename T>void write(T x)
    {
        if(x<0)
        {
            putchar('-');
            x=-x;
        }
        if(x>9) write(x/10);
        putchar(x%10+'0');
    }

    template<typename T> void read(T &x)
    {
        x = 0;char ch = getchar();int f = 1;
        while(!isdigit(ch)){if(ch == '-')f*=-1;ch=getchar();}
        while(isdigit(ch)){x = x*10+(ch-'0');ch=getchar();}x*=f;
    }
};
using namespace IO;
const int MAXN=1e8+10;
int bt[MAXN];
bool isnp[MAXN];
vector<int> primes;
void init1(int n)
{
    for (int i = 2; i <= n; i++)
    {
        if (!isnp[i])
            primes.push_back(i);
        for (int p : primes)
        {
            if (p * i > n)
                break;
            isnp[p * i] = 1;
            if (i % p == 0)
                break;
        }
    }
}
void init2(int n)
{
    for(auto x:primes)
    {
        for(auto y:primes)
        {
            if(y>x) break;
            if(x*y>n) break;
            bt[x*y]=1;
        }
    }
    
}
int main()
{
    #ifdef LOCAL_JUDGE
    HACK;
    #endif

    init1(MAXN);
    init2(MAXN);
    partial_sum(bt, bt + MAXN, bt);
    int t;
    read(t);
    while(t--)
    {
        int l,r;
        read(l);
        read(r);
        cout<<bt[r]-bt[l-1]<<endl;
    }

    #ifdef LOCAL_JUDGE
    RT;
    #endif
    ret 0;
}

0x61 optimization

The above code will still time out = =, There are two reasons: one is its own prefix and partial_ The sum () constant is relatively large and the efficiency is low, so it needs to be knocked by hand; Multiply the other two numbers to get another number. There must be x ≤ y x\le y x ≤ y, when typing beautiful numbers, the two-layer cycle can be from i i i start.

void init2(int n)
{
    f(i,1,primes.size()+1)
    {
        f(j,i,primes.size()+1)
        {
            if(primes[i]*primes[j]>MAXN) break;
            bt[primes[i]*primes[j]]=1;
        }
    }
    
}

0x70 another

=)

Topics: Algorithm Math