欧拉函数、莫比乌斯函数模板

struct EulerSieve {
private:
	int n;
	vector<int> phi;     // 欧拉函数数组
	vector<int> mu;      // 莫比乌斯函数数组
	vector<int> nextp;   // 最小质因子数组
	vector<int> prime;   // 素数列表
	vector<char> is_prime; // 素数标记数组

public:
	EulerSieve() : n(0) {}
	EulerSieve(int n) {
		init(n);
	}

	void init(int n) {
		phi.assign(n, 1);
		mu.assign(n, 1); // 初始化为1
		nextp.assign(n, 1);
		is_prime.assign(n, true);
		prime.clear();
		prime.reserve(1.2 * n / log(n)); // 素数定理预分配空间

		// 初始化边界条件
		is_prime[1] = false;
		phi[1] = 1;
		mu[1] = 1;
		nextp[1] = 1;

		for (int i = 2; i < n; i++) {
			if (is_prime[i]) {
				prime.push_back(i);
				phi[i] = i - 1;
				mu[i] = -1;
				nextp[i] = i;
			}
			for (int j = 0; j < (int)prime.size() && 1LL * i * prime[j] < n; j++) {
				int p = prime[j];
				int num = i * p;
				is_prime[num] = false;
				nextp[num] = p;
				if (i % p == 0) {
					phi[num] = phi[i] * p;
					mu[num] = 0;
					break;
				}
				else {
					phi[num] = phi[i] * (p - 1);
					mu[num] = -mu[i];
				}
			}
		}
	}

	int  get_Phi(int x) const {
		int res = x;
		for (int p = 2; x != 1; p += 1) {
			if (x % p == 0) {
				res = res / p * (p - 1);
				while (x % p == 0) {
					x /= p;
				}
			}
		}
		return res;
	}

	int get_phi(int x) const {
		return phi[x];
	}

	int get_mu(int x) const {
		return mu[x];
	}

	int get_nextp(int x) const {
		return nextp[x];
	}

	bool isprime(int x) const {
		return is_prime[x];
	}

	const vector<int>& get_primes() const {
		return prime;
	}
} sieve;
posted @ 2023-11-30 17:48  Ke_scholar  阅读(45)  评论(2)    收藏  举报