[扩展欧拉函数] 牛客2020多校第三场 F.Fraction Construction Problem

题目

[扩展欧拉函数] 牛客2020多校第三场 F.Fraction Construction Problem_第1张图片

已知ab 求出符合条件的cdef

思路

先想想a/b是不是最简形式

  • 如果gcd(a,b)!= 1
    则可令c/d=a2/b2+1 e/f=1
    即 c=(a+b)/gcd(a,b) d=b/gcd(a,b) e=1,f=1
  • 如果gcd(a,b)==1
    则(cf-ed)/df=a/b
    令df=b cf-ed=a
    如果知道df 则ce可根据扩展欧几里得求出
    那么df最好是互质的
    先令d为b的一个质因子 然后求出f (详见代码)
    最后根据exgcd计算出ce

代码

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#if __cplusplus >= 201103L
#include 
#include 
#endif
#define ll long long
using namespace std;
const int INF = 0x3f3f3f3f;
vector<int> v;
bool vis[2000010];
int vis1[2000010];
ll exgcd(ll a,ll b,ll &x1,ll &y1){
	if(b==0){
		x1=1;
		y1=0;
		return a;
	}
	int g=exgcd(b,a%b,x1,y1);
	int temp=x1;
	x1=y1;
	y1=temp-(a/b)*y1;
	return g;	
}
void p(int n){
	memset(vis,0,sizeof vis);
	for(int i=2;i<n;i++){
		if(!vis[i]){
			v.push_back(i);
			vis1[i]=i;
		}
		for(int j=0;j<v.size()&&i*v[j]<n;j++){
			vis[i*v[j]]=1;
			vis1[i*v[j]]=v[j];
			if(i%v[j]==0) break;
		}
	}
}
int main(){
	ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	int t;
	cin>>t;
	p(2000010);
	vis1[1]=1;
//	for(int i=1;i<=100;i++) cout<
	while(t--){
		ll a,b;
		cin>>a>>b;
		if(b==1) cout<<"-1 -1 -1 -1"<<endl;
		else{
			ll gcd=__gcd(a,b);
			if(gcd>1){
				cout<<(a+b)/gcd<<" "<<b/gcd<<" "<<1<<" "<<1<<endl;
			}
			else{
				//cout<<2<
				ll d1=vis1[b];
				ll d=1,f=b;
				while(f%d1==0){
					d*=d1,f/=d1;
				}
				//cout<
				if(f==1){
				   cout<<"-1 -1 -1 -1"<<endl;
            		continue;
				}
				ll c,e;
				exgcd(d,f,c,e);
				c=-c; 
				//cout<
				while(c<=0||e<=0){
					c+=f,e+=d;
				}
				c*=a,e*=a;
				cout<<e<<" "<<d<<" "<<c<<" "<<f<<endl;
			} 
		}
	} 
    return 0;
}

你可能感兴趣的:([扩展欧拉函数] 牛客2020多校第三场 F.Fraction Construction Problem)