Algorithm basics - mathematical knowledge - Euler function, fast power, extended Euclid, Chinese remainder theorem

Euler function

Insert image description here
Insert image description here

Coprime means that the greatest common factor of two numbers is only 1, which is reflected in the code a和b互质,则b mod a = 1 mod a (I don’t understand it very well at the moment, but it can be understood like this: the greatest common factor of a and b is 1, that is, when 1 is used as a divisor and b is used as a divisor, For the dividend a, the remainder is the same, that is, the remainder of 1/a is the same as b/a, that is) the role of the b mod a = 1 mod aEuler
function is to find the number of 1-n and n that are relatively prime

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <string>
#include <math.h>
#include <vector>
#include <queue>
#include <map>
#include <unordered_map>
using namespace std;

void get_eura(int x)
{
    
    
    int res = x;
    for (int i = 2; i <= x / i; ++ i)
    {
    
    
        if (x % i == 0)
        {
    
    
            //res = res * (1 - 1/i);或者res = res * (i - 1) / i;都不行,前者是浮点数1 后者会溢出
            res = res / i * (i - 1);
            while (x % i == 0)
            {
    
    
                x /= i;
            }
        }
    }
    if (x > 1) res = res / x * (x - 1);
    cout << res << endl;
}
void solve()
{
    
    
    int n;
    cin >> n;
    while (n -- )
    {
    
    
        int x;
        cin >> x;
        get_eura(x);
    }
}
int32_t main()
{
    
    
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    //cin >> T;
    while (T --) solve();
    return 0;
}

AcWing 874. Sieve method to find Euler function

Linear sieve + Euler function (with a little push formula)

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <string>
#include <math.h>
#include <vector>
#include <queue>
#include <map>
#include <unordered_map>
using namespace std;
const int N = 1e6 + 10;
int primes[N], st[N], eulers[N];
int cnt;
void get_eulers(int x)
{
    
    
    eulers[1] = 1;  
    for (int i = 2; i <= x; ++ i)//只是在线性筛的过程中顺便求了一下每个数的欧拉函数
    {
    
    
        if (!st[i])//1-n的质数
        {
    
    
            primes[cnt++] = i;
            eulers[i] = i - 1;
        }
        for (int j = 0; primes[j] <= x / i; ++ j)//1-n的合数//任何合数都含有质因数,4 = 1 * 2 * 1 * 2;
        {
    
    
            st[primes[j] * i] = 1;
            if (i % primes[j] == 0)
            {
    
    
                eulers[i * primes[j]] = eulers[i] * primes[j];
                break;//其实也相当于一个else
            }
            //eulers[i * primes[j]] = eulers[i] * primes[j] / primes[j] * (primes[j] - 1);
            eulers[i * primes[j]] = eulers[i] * (primes[j] - 1);
        }
    }
}
void solve()
{
    
    
    int n;
    cin >> n;
    get_eulers(n);
    long long res = 0; 
    for (int i = 1; i <= n; ++ i) res += eulers[i];
    cout << res;
}
int32_t main()
{
    
    
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    //cin >> T;
    while (T --) solve();
    return 0;
}

fast power

1 2 4 8 exponentially increase the time complexity of log

AcWing 875. Fast Power

long long qmi(int a, int b, int p)
{
    
    
    long long res = 1;
    while (b)
    {
    
    
        if (b & 1)
        {
    
    
            res = res * a % p;
        }
        a = a * (long long)a % p;
        b >>= 1;
    }
    return res;
}

AcWing 876. Fast power inversion element

Insert image description here
Euler function => Fermat's theorem => Fast power realization of Fermat's theorem calculation results

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <string>
#include <math.h>
#include <vector>
#include <queue>
#include <map>
#include <unordered_map>
using namespace std;

long long qmi(int a, int b, int p)
{
    
    
    long long res = 1;
    while (b)
    {
    
    
        if (b & 1) res = res * a % p;
        a = (long long)a * a % p;
        b >>= 1;
    }
    return res;
}
void solve()
{
    
    
    int n;
    cin >> n;
    while (n --)
    {
    
    
        int a, p;
        cin >> a >> p;
        if (a % p == 0) cout << "impossible" << endl;
        else cout << qmi(a, p - 2, p) << endl;//a需要与m互质,否则a不存在乘法逆元
    }
}
int32_t main()
{
    
    
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    //cin >> T;
    while (T --) solve();
    return 0;
}

Extended Euclidean (Pei Shu's theorem)

AcWing 877. Extended Euclidean Algorithm

Understanding the nature of recursion:
Insert image description here
Proof of Peishu's theorem and linear congruence equation:
Insert image description here

#include <cstdio>
#include <iostream>

using namespace std;

int exgcd(int a, int b, int &x, int &y)
{
    
    
    if (b == 0)
    {
    
    
        x = 1, y = 0;
        return a;
    }
    //d就是最大公约数,本题其实用不到
    int d = exgcd(b, a % b, y, x);//本题的精髓
    /*
    只是为了方便更改x和y的值,如果用
    d = exgcd(b, a % b, x, y);
    最后就解得 新x = y 新y = x - a / b * y
    那么代码就得这么写
    int t = y;
    y = x - a / b * y;
    x = t;
    显然比只要写一句 新y -= a / b * x; 麻烦
    */
    y -= a / b * x;
    return d;
}
void solve()
{
    
    
    int n;
    cin >> n;
    while (n -- )
    {
    
    
        int a, b, x, y;
        cin >> a >> b;
        exgcd(a, b, x, y);
        cout << x << " " << y << endl;
    }
}
int32_t main()
{
    
    
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    //cin >> T;
    while (T --) solve();
    return 0;
}

AcWing 878. Linear Congruential Equations

Linear congruence equations are solved using extended Euclid's theorem.
The derivation process of this question is as above.
Why do we need % m?
Insert image description here

#include <cstdio>
#include <iostream>

using namespace std;

int exgcd(int a, int b, int &x, int &y)
{
    
    
    if (b == 0)
    {
    
    
        x = 1, y = 0;
        return a;
    }
    else//其实不用else,上面满足直接return了,上面不满足也会走到下面 
    {
    
    
        int d = exgcd(b, a % b, y, x);
        y -= a / b * x;
        return d;
    }
}
void solve()
{
    
    
    int n;
    cin >> n;
    while (n -- )
    {
    
    
        int a, b, m, x, y;
        cin >> a >> b >> m;
        int d = exgcd(a, -m, x, y);
        if (b % d != 0) cout << "impossible" << endl;
        else cout << (long long)b / d * x % m << endl;
    }
}
int32_t main()
{
    
    
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    //cin >> T;
    while (T --) solve();
    return 0;
}

Chinese Remainder Theorem

Guess you like

Origin blog.csdn.net/chirou_/article/details/132668349