题目传送门: Codeforces
给n个数,a[ i ] ~ a[ n ],找到a的两个除数,d1(d1>1) 和 d2 (d2>1), 而且这两个除数满足gcd(d1+d2, a)=1,输出这n个数满足条件的d1和d2(如果答案有多个,随机输出), 如果不存在,d1=-1, d2=-1。
看到找除数,我们很容易想到唯一分解定理:
m = p 1 a 1 p 2 a 2 p 3 a 3 . . . . . . p n a n , ( p 1 , p 2.... p n 均 为 素 数 ) m = p1^{a1}p2^{a2}p3^{a3}......pn^{an}, (p1,p2.... pn 均为素数) m=p1a1p2a2p3a3......pnan,(p1,p2....pn均为素数)
对于最大公约数有两个基本性质:
1. g c d ( a , b ) = g c d ( a ± b , b ) = g c d ( a , b ± a ) ; 1.\ gcd(a,b)=gcd(a±b,b)=gcd(a,b±a); 1. gcd(a,b)=gcd(a±b,b)=gcd(a,b±a); 2. i f ( g c d ( a , b ) = = 1 ) , g c d ( a , b c ) = g c d ( a , c ) ; 2.\ if(gcd(a,b)==1), gcd(a,bc)=gcd(a,c); 2. if(gcd(a,b)==1),gcd(a,bc)=gcd(a,c);
将一个数分解为质因数后,进行如下操作:
d 1 = p 1 a 1 , d 2 = p 2 a 2 p 3 a 3 . . . . . . p n a n ; d1=p1^{a1}, d2=p2^{a2}p3^{a3}......pn^{an}; d1=p1a1,d2=p2a2p3a3......pnan; m = d 1 ∗ d 2 , g c d ( d 1 , d 2 ) = 1 ; m=d1*d2, \quad gcd(d1,d2)=1; m=d1∗d2,gcd(d1,d2)=1; g c d ( d 1 , d 2 ) = g c d ( d 1 + d 2 , d 2 ) = g c d ( d 1 , d 1 + d 2 ) = 1 gcd(d1,d2)=gcd(d1+d2,d2)=gcd(d1,d1+d2)=1 gcd(d1,d2)=gcd(d1+d2,d2)=gcd(d1,d1+d2)=1则: g c d ( d 1 + d 2 , d 1 ∗ d 2 ) = g c d ( d 1 + d 2 , m ) = g c d ( d 1 , d 1 ) = 1 gcd(d1+d2,d1*d2)=gcd(d1+d2,m)=gcd(d1,d1)=1 gcd(d1+d2,d1∗d2)=gcd(d1+d2,m)=gcd(d1,d1)=1
对于此题,我们先求出0~100000之间所有素数,然后对于每一个a[i], 利用唯一分解定理求解,如果a[i]是素数,直接d1=d2=-1, 确保d1>1,d2>1。
#include
using namespace std;
#define ll long long
const int Max=1e6+7;
int d1[Max], d2[Max], a[Max];
int prime[100006];
bool isPrime(int n){
if(n==2 ||n==3) return true;
if(n%6!=1 && n%6!=5) return false;
int nsqrt=sqrt(n);
for(int i=5; i<=nsqrt; i+=6){
if(n%i==0 || n%(i+2)==0 ) return false;
}
return true;
}
// 筛选素数
void getprime(){
int index=0;
for(int i=2; i<=100000; i++){
if( isPrime(i) ) prime[++index]=i;
}
}
int main(){
ios::sync_with_stdio(0);
getprime();
int n; scanf("%d",&n);
memset(d1,0,sizeof d1); memset(d2,0,sizeof d2);
for(int i=1; i<=n; i++) scanf("%d",&a[i]);
for(int i=1; i<=n; i++){
if(isPrime(a[i])){
d1[i]=d2[i]=-1; continue;
}
int index=1;
int t=a[i];
while(t>1){
if(t%prime[index]==0){ // 找出 p1^a1
int c=prime[index];
t=t/prime[index];
while(t%prime[index]==0){
c*=prime[index];
t/=prime[index];
if(t<=1) break;
}
d1[i]=c; d2[i]=a[i]/c;
break;
}
index++;
}
if(d1[i]<=1 || d2[i]<=1) d1[i]=d2[i]=-1;
}
for(int i=1; i<=n; i++){
if(i==1) printf("%d",d1[i]);
else printf(" %d",d1[i]);
} printf("\n");
for(int i=1; i<=n; i++){
if(i==1) printf("%d",d2[i]);
else printf(" %d",d2[i]);
} printf("\n");
return 0;
}