扩展欧拉函数求模

扩展欧拉定理

1、定义:若 \(gcd(a,p)=1\),则 \(a^{\varphi(p)} \equiv 1 \ (mod \ p)\)

2、扩展欧拉定理求模:

\(\left\{\begin{array}{l} a^{b \ mod \ \varphi(p)}, \qquad \qquad gcd(a,p)=1 \\ a^b, \qquad \qquad \qquad \quad gcd(a,p) \ne 1,b < \varphi(p) \\ a^{b \ mod \ \varphi(p) \ + \ \varphi(p)}, \quad \ \ \ gcd(a,p) \ne 1,b \ge \varphi(p) \end{array}\right.\)

3、扩展欧拉定理一般用于 \(b\) 很大的快速幂。

struct pre{
    int N;
    vector<i64> preim;
    vector<i64> a;
    pre(int N_) : a(N_ + 1) {
        N = N_;
        for (i64 i = 2; i <= N; i++) {
            if (!a[i]) {
                a[i] = i;
                preim.push_back(i);
            }
            for (auto p : preim) {
                if (i * p > N) break;
                a[i * p] = p;
                if (a[i] == p) {
                    break;
                }
            }
        }
    }
    
    inline bool ispreim(i64 x) {
		return (a[x] == x && x != 0);
	}
};

pre t(1000000);

struct getphi{
    inline i64 calc(i64 x) {
        i64 ans = x;
        for (auto p : t.preim) {
            if (p * p > x) break;
            if (x % p == 0) {
                ans = ans / p * (p - 1);
                while (x % p == 0) x /= p;
            }
        }
        if (x > 1) ans = ans / x * (x - 1);
        return ans;
    }
};

getphi t2;

struct exphi{
    inline i64 exqp(i64 a, string &s, i64 p = 1e9 + 7) {
        i64 n = s.size();
        i64 b = 0;
        i64 phi = t2.calc(p);// 如果模数是一样的,可以把模数在全局变量中求出来即可
        bool f = 0;
        for (i64 i = 0; i < n; i++) {
            b *= 10;
            b += (s[i] - '0');
            if (b >= phi) {
                f = 1;
                b %= phi;
            }
        }
        
        if (__gcd(a, p) != 1 && f) b += phi;
        
        a %= p;
        i64 res = 1;
        while (b) {
            if (b & 1) res = res * a % p;
            a = a * a % p;
            b >>= 1;
        }
        return res;
    }
};

另一种版本的扩展欧拉定理,主要处理 \(p\) 不超过 \(1e7\) 的模数

struct getphi{
    int N;
    vector<i64> preim;
    vector<i64> a;
    vector<i64> phi;
    getphi(int N_) : a(N_ + 1), phi(N_ + 1) {
        N = N_;
        phi[1] = 1;
        for (i64 i = 2; i <= N; i++) {
            if (!a[i]) {
                a[i] = i;
                phi[i] = i - 1;
                preim.push_back(i);
            }
            for (auto p : preim) {
                if (i * p > N) break;
                a[i * p] = p;
                if (a[i] == p) {
                    phi[i * p] = phi[i] * p;
                    break;
                }
                phi[i * p] = phi[i] * phi[p];
            }
        }
    }
};

getphi t(1000000);

struct exphi{
    inline i64 exqp(i64 a, string &s, i64 p = 100007) {
        int n = s.size();
        i64 b = 0;
        i64 phi = t.phi[p];
        bool f = 0;
        for (i64 i = 0; i < n; i++) {
            b *= 10;
            b += (s[i] - '0');
            if (b >= phi) {
                f = 1;
                b %= phi;
            }
        }
        
        if (__gcd(a, p) != 1 && f) b += phi;
        
        i64 res = 1;
        a %= p;
        while (b) {
            if (b & 1) res = res * a % p;
            a = a * a % p;
            b >>= 1;
        }
        return res;
    }
};
posted @ 2024-08-29 23:45  grape_king  阅读(28)  评论(0)    收藏  举报