【藍橋杯】算法訓練 素因子去重


算法訓練 素因子去重  
時間限制: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。關於這兩個過程可以戳以前的博客: 埃氏篩法打印素數表    算術基本定理:整數質因子分解
 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 } 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM