【解题报告】2020牛客暑期多校集训营第三场F题 扩欧

题目大意:求解c/d-e/d=a/b的任意正整数解,其中a,b已知,求c,d,e,f

官方题解:分成三种情况(判断带顺序)

<1>a,b不互质:因为有个公因数g=gcd(a,b),所以d和f就可以取b/g,凑吧凑吧就能出来解

<2>对b质因数分解,分解出来的质数个数小于等于1:注意,此时是建立在a,b互质的情况下,所以a/b的最简形式就是其本身,但是d,f<b,所以此时d和f的对应质因数的指数就不可能大于b的,c/d-e/f计算化简后的分母的对应质因数的指数也就不可能大于b的,所以这种情况无解

<3>b的相异质因数个数超过1个(第二种情况的补集):此时我们就可以得到互质的d和f,使得df=b,从而可以得到方程cf-ed=a,因为此时gcd(d,f)=1,所以肯定有解,用扩欧求解一下,得到c,之后找到特解:c=ac,然后我们求c的最小正数解:(c%d+d)%d,根据c的值再求出e的正数解。

这道题就细节很多,然后还容易T…质因数分解那块要打素数表,然后在分解前后还需要稍微剪剪枝。大概就是这样。

AC代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn=2e6+10;
LL exgcd(LL a,LL b,LL &x,LL &y)
{
	if(b==0){
		x=1,y=0;
		return a;
	}
	LL d=exgcd(b,a%b,x,y); 
	LL z=x;x=y;y=z-y*(a/b);
	return d;
}
vector<int> prime;//存储2~N的所有素数 
bool v[maxn];//合数标记 
void find_primes(int n)
{
	memset(v,false,sizeof(v));
	for(int i=2;i<=n;i++){
		if(v[i]) continue;
		prime.push_back(i);
		//优化:从x^2开始,(x+1)*x...到N/x*x结束,标记为合数即可 
		for(int j=i;j<=n/i;j++) v[i*j]=true; 
	}
}
LL a,b,c,d,e,f;
int main()
{
	find_primes(maxn-5);
	int t;scanf("%d",&t);
	while(t--){
		scanf("%lld%lld",&a,&b);
		if(b==1){
			printf("-1 -1 -1 -1\n");
			continue;
		}
		LL x,y;
		LL g=exgcd(a,b,x,y);
		if(g>1){
			c=(a+g)/g,d=b/g;
			e=1,f=b/g;
			printf("%lld %lld %lld %lld\n",c,d,e,f);
			continue;
		}
		if(!v[b]){
			printf("-1 -1 -1 -1\n");
			continue;
		}
		LL tempb=b;
		d=1;
		for(int i=0;i<prime.size();i++){
			if(tempb%prime[i]==0){
				while(tempb%prime[i]==0)
					d*=prime[i],tempb/=prime[i];
				break;
			}
		}
		if(tempb==1){
			printf("-1 -1 -1 -1\n");
			continue;
		}
		f=b/d;
		g=exgcd(f,d,c,e);
		if(a%g!=0){
			printf("-1 -1 -1 -1\n");
			continue;
		}
		c=c*a/g;e=e*a/g;
		LL d1=d/g;
		c=(c%d1+d1)%d1;
		LL k=(a-f*c)/d1;
		if(k<0) k=0;
		c=c+(k+1)*d1;
		e=(f*c-a)/d;
		printf("%lld %lld %lld %lld\n",c,d,e,f);
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值