階乘質因數分解

kuailedetongnian發表於2024-11-01

\(1 \leq n \leq 10^6\), 唯一分解(質因數分解) \(n!\),輸出 \(p_i,c_i\)

階乘分解 AcWing197

思路

前置知識:線性篩 (質數判定的演算法4)。

顯然 \(n!\) 的每個質因子都小於等於 \(n\)

因為 \(n! = n(n-1)(n-2)(n-3)\cdots 3 \cdot 2 \cdot 1\),所以質數 \(p\)\(n!\) 出現的次數為 \(p\)\(1\sim n\) 出現的次數。

對於 \(i=1,2,3\dots n\)

對於 \(p\):若有 \(p|i\),則 \(p\) 出現次數+1

對於 \(p^2\):若有 \(p^2|i\),則 \(p\) 出現次數 +1,而不是 +2,因為其中一個 \(p\)\(p|i\) 時被統計了。

對於 \(p^3\):若有 \(p^3|i\),則 \(p\) 出現次數 +1,而不是 +3,因為其中一個 \(p\)\(p|i\) 時被統計了,另一個 \(p\)\(p^2|i\) 時被統計了。

...

\(p\)\(n!\) 中出現的次數為 \(\lfloor\frac{n}{p}\rfloor + \lfloor\frac{n}{p^2}\rfloor + \lfloor\frac{n}{p^3}\rfloor + \cdots + \lfloor\frac{n}{p^{\lfloor\log_p{n}\rfloor}}\rfloor = \sum\limits_{p^k\leq n}{\lfloor\frac{n}{p^k}\rfloor}\)

綜上有以下步驟:

  • 線性篩求 \(1 \sim n\) 內的質數。\(O(n)\)
  • 遍歷 \(1 \sim n\) 內的質數,找出質數\(p\)\(p|n\)\(O(\pi(n))=O(\frac{n}{\log n})\)
    • 對於質數 \(p\),求出在 \(n!\) 中出現的次數。\(O(\log n)\)

\(\pi(x)\) 是小於等於 \(x\) 的質數個數,約等於 \(\frac{n}{\log n}\)

綜上時間複雜度為 \(O(n + \frac{n}{\log n} \cdot \log n) = O(n)\)

程式碼實現

int n;
long long v[N];
::std::vector<int> ps;
int main() {
	scanf("%d", &n);

	/* 線性篩 */
	for(int i = 2; i <= n; i++)
	{
		if(!v[i])
			v[i] = i, ps.push_back(i);
		for(int j : ps)
			if(v[i] < j || j > n / i) break;
			else v[i * j] = j;
	}

	for(int i : ps)
	{
		ll p = i;
		int c = 0;
		while(p <= n)
		{
			c += n / p;
			p *= i;
		}
		printf("%d %d\n", i, c);
	}
	return 0;
}

相關文章