1. 程式人生 > 實用技巧 >2020牛客多校三 F-Fraction Construction Problem (歐幾里得+構造)

2020牛客多校三 F-Fraction Construction Problem (歐幾里得+構造)

題目連結:傳送門


思路:

1.考慮 a b 不互質,即 r=gcd(a,b)>1 ;那麼可以構造出 c=(a/r)+1 d=b/r e=1 f=b/r (要求d<b && f<b ,因此 r 必須大於1)

2.考慮 a b 互質,即 r=gcd(a,b)=1; 那麼可以得到式子 (cf-ed)/df = a/b ,可以令d*f = b, 那麼可以根據b的值構造出d f,然後解不定方程 cf - ed = a ,其中 a d f 是已知係數;

 根據不定方程可知 gcd(d,f) = 1 ,因為a與b互質,那麼肯定a與gcd(d,f) 互質 ,a%1=0;  所以必須要構造出互質d f,這樣就必須要求b有兩個及以上的質因子個數。

其餘情況無解。

#include<bits/stdc++.h>
/*
#include<cstdio>
#include<cmath>
#include<cstring>
#include<vector>
#include<cctype>
#include<queue>
#include<algorithm>
#include<map>
#include<set>
*/
#pragma GCC optimize(2)
using namespace std;
typedef 
long long LL; typedef unsigned long long uLL; typedef pair<int,int> pii; typedef pair<LL,LL> pLL; typedef pair<double,double> pdd; const int N=2e6+5; const int M=8e5+5; const int inf=0x3f3f3f3f; const LL mod=1e9+7; const double eps=1e-5; const long double pi=acos(-1.0L); #define ls (i<<1) #define
rs (i<<1|1) #define fi first #define se second #define pb push_back #define eb emplace_back #define mk make_pair #define mem(a,b) memset(a,b,sizeof(a)) LL read() { LL x=0,t=1; char ch; while(!isdigit(ch=getchar())) if(ch=='-') t=-1; while(isdigit(ch)){ x=10*x+ch-'0'; ch=getchar(); } return x*t; } int cnt[N],num[N]; int gcd(int x,int y) { return y==0?x:gcd(y,x%y); } int exgcd(int a,int b,LL &x,LL &y) { //printf("...\n"); if(b==0) { x=1; y=0; return a; } LL x1,y1; int t=exgcd(b,a%b,x1,y1); x=y1; y=x1-a/b*y1; return t; } void init() { for(int i=2;i*i<N;i++) { if(num[i]) continue; num[i]=i; for(int j=i*i;j<N;j+=i) { if(num[j]) continue; num[j]=i; cnt[j]++; int t=j; while(t%i==0) t/=i; if(t>1) cnt[j]++; } } } int main() { init(); //for(int i=25;i<=30;i++) printf("..%d %d\n",num[i],cnt[i]); int T=read(); while(T--) { int a=read(),b=read(); int r=gcd(a,b); //printf("r = %d\n",r); if(r>1) { printf("%d %d %d %d\n",a/r+1,b/r,1,b/r); continue; } if(cnt[b]<2) { printf("-1 -1 -1 -1\n"); continue; } LL d=1,f=b; while(f%num[b]==0) f/=num[b]; d=b/f; LL x,y; exgcd(f,d,x,y); //printf("%d %d") y=-y; while(x<=0||y<=0) x+=d,y+=f;//x 是和"b"相關的,這裡的b指的就是d; printf("%lld %lld %lld %lld\n",x*a,d,y*a,f); } }
View Code