Codeforces D. Two Divisors (数论,线性筛)

https://codeforces.ml/contest/1366/problem/D
(题目链接如上↑)

题解:
1.首先,gcd(x,y)=gcd(x+y,x*y)
证明如下:
gcd有两点性质:
(1) gcd(a,b)=gcd(a-b,b),gcd(a,b)=gcd(a+b,b)
(2) 若gcd(a,c)=1,则gcd(a,bc)=gcd(a,b)
下面正式开始证明:
由性质1可得: gcd(x,y)=1 -> gcd(x+y,y)=1
由性质2可得: gcd(x+y,xy)=gcd(x+y,x)
再由性质1可得: gcd(x+y,x)=gcd(y,x)=1
故:gcd(x+y,x*y)=gcd(x,y)=1

2.由唯一分解定理,可构造 d1 = q1 ^ k1 , d2 =q2 ^ k2… qn ^ kn
那么,(d1+d2)%p1!=0,……(d1+d2)%pn!=0
故(d1+d2)和ai互质。

3.这题数据的范围为1e7,所以需用欧拉筛,先找出1e7范围内的最小质因数。

线性筛模板:

int prime[1100000],primesize;
bool isprime[11000000];
void getlist(int listsize){
    memset(isprime,1,sizeof(isprime));
    isprime[1]=false;
    for(int i=2;i<=listsize;i++){
        if(isprime[i])prime[++primesize]=i;
         for(int j=1;j<=primesize&&i*prime[j]<=listsize;j++) {
            isprime[i*prime[j]]=false;
            if(i%prime[j]==0) break;//保证了每个合数只会被它的最小素因子筛掉,就把复杂度降到了O(N)
        }
    }
}

AC代码:

#include  
using namespace std;
const int maxa=10000005,maxn=500005;
int prime[maxa],minprime[maxa];
int a[maxn],b1[maxn],b2[maxn];
int euler(int n){
    int c=0;
    for(int i=2;i<=n;i++){
        if(!minprime[i]) prime[++c]=i,minprime[i]=i;
        for(int j=1;j<=c&&i*prime[j]<=n;j++){
            minprime[i*prime[j]]=prime[j];
            if(i%prime[j]==0) break;
        }
    }
    return c;
}
int main(){
	int n;
	cin>>n;
	euler(1e7);
	for(int i=0;i<n;i++){
		cin>>a[i];
		int x=a[i];
		int now,mi=minprime[x];
		while(x%mi==0){
			x/=mi; now*=mi;
		}
		if(x!=1&&now!=1){
			b1[i]=mi; b2[i]=x;
		}
		else{
			b1[i]=-1; b2[i]=-1;
		}
	}
	for(int i=0;i<n;i++){
		if(i==0) cout<<b1[i];
		else cout<<" "<<b1[i];
	}
	cout<<endl;
	for(int i=0;i<n;i++){
		if(i==0) cout<<b2[i];
		else cout<<" "<<b2[i];
	}
	cout<<endl;
	return 0;
}

你可能感兴趣的:(Codeforces,数论题)