# Prime Number# Math# String Manipulation# Precomputation

c666 - 質數乘積

🔗 前往 ZeroJudge 原題

題目描述

題目要求計算前 n 個質數的乘積。給定一個整數 n,程式需要輸出前 n 個質數相乘的結果。

解題思路

此題的核心在於高效地計算質數並進行大數乘法。程式首先使用埃拉托斯特尼篩法 (Sieve of Eratosthenes) 預先計算出前 5000 個質數,並將其儲存在 prime 陣列中。然後,程式使用一個 ans 陣列來儲存前 i 個質數的乘積,透過迭代地將前一個乘積與當前質數相乘來計算。由於質數乘積可能非常大,程式使用字串 (string) 來儲存和處理這些大數。mult 函數實現了大數乘法的邏輯,它將一個字串表示的數字乘以一個整數,並返回結果字串。最後,程式讀取輸入的 n,並輸出 ans[n-1],即前 n 個質數的乘積。

複雜度分析

  • 時間複雜度: O(N^2 + M * L),其中 N 是篩選質數的上限 (約為 48620),M 是輸入 n 的最大值 (5000),L 是大數乘法的平均長度。埃拉托斯特尼篩法的時間複雜度為 O(N log log N),近似為 O(N^2)。大數乘法 mult 的時間複雜度為 O(L^2),由於需要進行 M 次乘法,因此總時間複雜度為 O(M * L^2)。
  • 空間複雜度: O(M + N),其中 M 是 ans 陣列的大小 (5001),N 是篩選質數所需的空間 (約為 48621)。

程式碼

#include <iostream>
using namespace std;
int it=0;
string ans[5001]={"2"};
int prime[5001];
string mult(string x,int y){
	int tmp[21001]={0};
	int xl=x.length(),it=0;
	string rt;
	while(y){
		int t=y%10;
		for(int i=0;i<xl;++i)
			tmp[it+i]+=(x[xl-1-i]-48)*t;
		y/=10;
		++it;
	}
	for(int i=0;i<21001;++i)
		if(tmp[i]>=10){
			tmp[i+1]+=tmp[i]/10;
			tmp[i]%=10;
		}
	for(int i=21000;i>=0;--i)
		if(tmp[i]!=0){
			it=i;
			break;
		}
	for(int i=it;i>=0;--i)
		rt+=tmp[i]+'0';
	return rt;
}
bool p[50001]={1,1};
int main(){
	cin.tie(0);ios::sync_with_stdio(false);
	for(int i=2;i<=221;++i)
		for(int j=i+i;j<=48620;j+=i)
			p[j]=1;
	for(int i=0;i<=48620&&it<=5000;++i)
		if(p[i]==0)
			prime[it++]=i;
	for(int i=1;i<=5000;++i)
		ans[i]=mult(ans[i-1],prime[i]);
	while(cin >> it)
		cout << ans[it-1] << "\n";
}

Discussion