【藍橋杯】算法訓練 素因子去重
阿新 • • 發佈:2019-02-13
6.0 == argc 兩個 時間 直接 .html html urn 算法訓練 素因子去重
時間限制:1.0s 內存限制:256.0MB
問題描述
給定一個正整數n,求一個正整數p,滿足p僅包含n的所有素因子,且每個素因子的次數不大於1
輸入格式
一個整數,表示n
輸出格式
輸出一行,包含一個整數p。
樣例輸入
1000
樣例輸出
10
數據規模和約定
n<=10^12
樣例解釋:n=1000=2^3*5*3,p=2*5=10 題目還是很好理解的,一看到題,我的第一個思路就是先打印素數表,然後直接用整數的質因子分解來做,結果是耗時15ms,內存984.0KB。關於這兩個過程可以戳以前的博客:埃氏篩法打印素數表 算術基本定理:整數質因子分解
樣例解釋:n=1000=2^3*5*3,p=2*5=10 題目還是很好理解的,一看到題,我的第一個思路就是先打印素數表,然後直接用整數的質因子分解來做,結果是耗時15ms,內存984.0KB。關於這兩個過程可以戳以前的博客:埃氏篩法打印素數表 算術基本定理:整數質因子分解
1#include <iostream> 2 using namespace std; 3 4 bool is_prime[10005]; 5 int prime[10005]; 6 void sieve(int n){ 7 int p = 0; 8 for(int i = 2; i <= n; i++) is_prime[i] = true; 9 for(int i = 2; i <= n; i++){ 10 if(is_prime[i]){ 11 prime[p++] = i;12 for(int j = 2*i; j<=n; j+=i) is_prime[j] = false; 13 } 14 } 15 } 16 17 int main(int argc, char *argv[]) { 18 sieve(10005); 19 long long n, ans = 1; 20 cin>>n; 21 for(int i = 0;prime[i]*prime[i]<=n; i++){ 22 if(n % prime[i] == 0){ 23 ans *= prime[i]; 24 while(n % prime[i] == 0) n /= prime[i]; 25 } 26 } 27 ans *= n; 28 cout<<ans<<endl; 29 30 return 0; 31 }
後來發現自己把題目理解復雜了,下面給出我的第二個思路,耗時46ms,內存936.0KB。
1 #include <iostream> 2 using namespace std; 3 4 int main(int argc, char *argv[]) { 5 long long n, ans = 1; 6 cin>>n; 7 for(int k = 2; n != 1; k++){ 8 if(n % k == 0){ 9 ans = ans * k; 10 while(n % k == 0) n /= k; 11 } 12 } 13 cout<<ans<<endl; 14 15 return 0; 16 }
這個方法也很直接,從最小的質數2開始循環,判斷當前的數k能不能整除n,如果可以就說明k是n的一個質因數,讓ans乘上k,再讓n除以k直到n不再包含k為止。每次循環k++。有個巧妙的地方在於,因為每次循環結束得到的新的n都已經不再包含上一個質因子k,所以下一次滿足整除條件的k一定還是質數(有一點埃氏篩法的感覺)。比如取n=1000,它最小的質因子是2,在k=2的這一輪循環結束後,新的n為125,已經不再包含2,所以k=4時,n已經不再能被4整除,直接進入下一輪循環k=5。這一輪結束後,n=1,說明所有的質因子已經被找到,循環結束。
第三種方法是在網上看到的題解,我在循環那邊優化了一下,也很簡單直接,有一個素性判斷的is_prime函數,然後直接循環判斷質因子。下面是代碼,耗時0ms,內存936.0KB。
1 #include <iostream> 2 using namespace std; 3 4 bool is_prime(long long n){ //判斷n是否為素數 5 for(long long i = 2; i*i <=n; i++) 6 if(n%i ==0) return false; 7 return true; 8 } 9 10 int main(int argc, char *argv[]) { 11 long long n, m = 1; 12 cin>>n; 13 for(long long i = 2; i*i<=n; i++){ 14 if(n%i == 0 && is_prime(i)){ 15 m *= i; 16 while(n%i==0) n/=i; 17 } 18 } 19 m *= n; 20 cout<<m<<endl; 21 22 return 0; 23 }
最後一種也大同小異,用到了集合set元素,網上看到的題解。耗時46ms,內存932.0KB。(其實幾種都差不多)
1 #include<iostream> 2 #include<set> 3 using namespace std; 4 5 set<int> s; 6 bool isPrime(long long n){ 7 for(int i=2; i*i <= n; i++) 8 if(n%i == 0) return false; 9 return true; 10 } 11 12 int main(){ 13 long long n, ans=1; 14 cin>>n; 15 for(int i=2; n!=1; i++) 16 if(n%i==0 && isPrime(i)){ 17 s.insert(i); 18 while(n%i==0) n/=i; 19 } 20 for(set<int>::iterator it=s.begin(); it!=s.end(); it++) 21 ans *= (*it); 22 cout<<ans<<endl; 23 24 return 0; 25 }
【藍橋杯】算法訓練 素因子去重