应该是 2020暑假多校 F.Fraction Construction Problem

应该是 2020暑假多校 F.Fraction Construction Problem_第1张图片
给我们 a b 问能不能构造出前面两个分数,看到这个首先联想到exgcd 拓欧
至于构造,不妨利用b的约数 在此我取的是b的最小质因子的全部幂次的数作为一个分母,另一个数直接用b除就好了, 然后问题转为求解 fx+dy=a

  • 这不就是很简单了      
    
  • 先套exgcd 然后对x0 y0 协调一下就OK了
  • 以上做法只适用于gcd(a,b)=1
  • 如果b=1 直接全部是-1 -1 -1 -1 不可能构造
  • 对于gcd(a,b) 不等于1 更好想了,直接用b/gcd(a,b) 作为分母, 分子直接用a/gcd(a,b) +1 另一个用1 构造 完事 上代码
#include
#include
#include
#include
#include
#include
#include 
#include 
#include 
#define ll long long
#define inf 0x3f3f3f3f
#define mods 1000000007
#define modd 998244353
#define PI acos(-1)
#define fi first
#define se second
#define lowbit(x) (x&(-x))
#define mp make_pair
#define pb push_back
#define si size()
#define E exp(1.0)
#define fixed cout.setf(ios::fixed)
#define fixeds(x) setprecision(x)
#define IOS ios::sync_with_stdio(false);cin.tie(0)
 using namespace std;
 ll gcd(ll a,ll b){if(a<0)a=-a;if(b<0)b=-b;return b==0?a:gcd(b,a%b);}
template<typename T>void read(T &res){bool flag=false;char ch;while(!isdigit(ch=getchar()))(ch=='-')&&(flag=true);
for(res=ch-48;isdigit(ch=getchar());res=(res<<1)+(res<<3)+ch - 48);flag&&(res=-res);}
ll exgcd(ll a,ll b,ll &x,ll &y){
    if (!b){
        x=1,y=0;
        return a;
    }
    ll ans=exgcd(b,a%b,y,x);
    y-=(a/b)*x;
    return ans;
}

const int maxn=2e6+100;
ll prime[maxn],minprime[maxn];
void euler()  //欧拉筛
{  //  minprime[1]=1;
    ll cnt=0,i,j;
    for(i=2; i<=maxn; i++)
    {
        if(!minprime[i])
            prime[++cnt]=i,minprime[i]=i;
        for(j=1; j<=cnt&&i*prime[j]<=maxn; j++)
        {
            minprime[i*prime[j]]=prime[j];
            if(i%prime[j]==0)
                break;
        }
    }
}
int  main(){
euler();
ll t;
read(t);
while(t--){

 ll a,b;
 read(a);
 read(b);
 if(b==1){
    printf("-1 -1 -1 -1\n");
  continue;

 }
 ll g=gcd(a,b);
 if(g==1){
ll  d=1,f=1;
ll flag=0;
 ll s=minprime[b];
 while(b%s==0){b=b/s;d=d*s; }
 if(b!=1){flag++;f=b;}
 if(flag==0){
  printf("-1 -1 -1 -1\n");
  continue;
 }
 else{
   ll x,y,pos=0;
  ll g=exgcd(f,d,x,y);
   for(int j=0;;j++){
  if(x>0&&y<0){
    pos=j;
    break;
  }
  x=x+d;
  y=y-f;
  }
  x=x+(pos+1)*d;
  y=y-(pos+1)*f;
  x=x*a;
  y=y*(-a);
 printf("%lld %lld %lld %lld\n",x,d,y,f);
 continue;
 }
}
ll oppp=1;
printf("%lld %lld %lld %lld\n",a/gcd(a,b)+1,b/gcd(a,b),oppp,b/gcd(a,b));
}
return 0;
}

在这里插入图片描述
卡了我一下午原来是这个地方演了自己 (太操了应该是 2020暑假多校 F.Fraction Construction Problem_第2张图片

你可能感兴趣的:(笔记)