1. 程式人生 > 實用技巧 >Educational Codeforces Round 89 (Rated for Div. 2)D. Two Divisors 線性篩質因子

Educational Codeforces Round 89 (Rated for Div. 2)D. Two Divisors 線性篩質因子

題目連結:D:Two Divisors

題意:

給你n個數,對於每一個數vi,你需要找出來它的兩個因子d1,d2。這兩個因子要保證gcd(d1+d2,vi)==1。輸出的時候輸出兩行,第一行輸出每一個數vi對應的第一個因子d1,第二行對應位置輸出第二個因子d2

題解:

最大公約數有兩個基本性質如下:

  1. gcd(a,b)=gcd(a±b,b)=gcd(a,b±a);
  2. if(gcd(a,b)==1)gcd(a,bc)=gcd(a,c);

設p1、p2、p3...pm是一個數x的所有質因子,我們設d1=p1^k(它的意思就是p1的k次方),d2=x/d1。這個k要保證d2%p1!=0

而且還會有x=p1^k1*p2^k2*...*pk^km=d1*d2

我們很容易就知道gcd(d1,d2)==1,畢竟d1是質因子p1的平方所得

那麼gcd(d1,d2)=gcd(d1+d2,d1)=gcd(d1+d2,d2),又因為x=d1*d2

所以d1+d2就和x互質

因為樣例有好多組,所以我們就先通過線性篩的方法進行預處理,具體看程式碼:

 1 #include<stdio.h>
 2 #include<algorithm>
 3 #include<iostream>
 4 #include<string>
 5 #include<queue>
 6
#include<deque> 7 #include<string.h> 8 #include<map> 9 #include <iostream> 10 #include <math.h> 11 using namespace std; 12 typedef long long ll; 13 const int maxn=1e7+10; 14 int minprim[maxn],prim[maxn],v[maxn],ans1[maxn],ans2[maxn]; 15 int finds(int n) //線性篩 16 { 17 int
num=0; //num為從2到maxn這個範圍內所有質數(也就是素數)的個數 18 for(int i=2;i<=n;++i) 19 { 20 //minprim數組裡面儲存的是i的最小質因子(所謂質因子也就是為素數的因子) 21 if(!minprim[i]) prim[++num]=i,minprim[i]=i; 22 for(int j=1;j<num && prim[j]*i<=n;++j) 23 { 24 minprim[i*prim[j]]=prim[j]; 25 } 26 } 27 return num; 28 } 29 int main() 30 { 31 int n; 32 finds(1e7); 33 scanf("%d",&n); 34 for(int i=1;i<=n;++i) 35 scanf("%d",&v[i]); 36 //printf("%d***\n",minprim[24]); 37 for(int i=1;i<=n;++i) 38 { 39 int ans=minprim[v[i]],temp; 40 v[i]/=ans; 41 temp=ans; 42 while(v[i]%ans==0) v[i]/=ans,temp*=ans; 43 if(v[i]==1) 44 ans1[i]=ans2[i]=-1; 45 else ans1[i]=temp,ans2[i]=v[i]; 46 47 } 48 for(int i=1;i<=n;++i) 49 { 50 if(i==n) printf("%d\n",ans1[i]); 51 else printf("%d ",ans1[i]); 52 } 53 for(int i=1;i<=n;++i) 54 { 55 if(i==n) printf("%d\n",ans2[i]); 56 else printf("%d ",ans2[i]); 57 } 58 return 0; 59 }