6

发布时间 2023-06-08 17:46:37作者: nannan4128
Benefit

题意:使得 \(\operatorname{lcm}(a,b)=c\) 成立最小的 \(b\),若没有满足条件的$ b$,输出 NO SOLUTION

\(1≤t≤10^5,1\le a,c\le 10^7\)

题解:

法一:

\(\operatorname{lcm} = \dfrac{ab}{\gcd(a,b)} = c\)

\(\dfrac{b}{\gcd(a,b)} = \dfrac{c}{a}\)

\(\because \dfrac{b}{\gcd(a,b)}\)是整数,那\(\dfrac{c}{a}\)也要是整数,即若\(c\bmod a \neq 0\)则输出NO SOLUTION

否则的话我们去找合适的\(b\)

\(d = \dfrac{c}{a}\),设函数\(f(a,d)\)为使得\(\dfrac{x}{\gcd(a,x)}=d\)成立的最小的\(x\),再分类讨论:

  1. \(gcd(a,d)=1\)时,显然\(x = d\)

  2. \(\gcd(a,d)>1\)时,设\(k = \gcd(a,x)\)代入\(f(a,d)\)\(x = kd\)

    则有\(k = \gcd(a,kd)\)

    \(\gcd(a,d)=g\),则\(\frac{k}{g}=\gcd(\frac{a}{g},\frac{d}{g}k)\)

    \(\because \dfrac{a}{g}\)\(\dfrac{d}{g}\)已经是互质的,则\(\frac{k}{g}=\gcd(\frac{a}{g},k)\)

    移项得:\(\frac{k}{gcd(\frac{a}{g},{k})} = g\)

    通过递归求解\(f(\frac{a}{g},g)\)求得\(k\)

    最后答案为\(x = kd\)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b)
{
	return b?gcd(b,a%b):a;
}
/*
		lcm(a,b) = c;
		a*b/gcd(a,b) = c;
		b/gcd(a,b) = c/a;
		d = c/a;
		f(a,d) = x ==> x/gcd(a,x) = d;
		if(gcd(a,d)==1) x = d;
		else(gcd(a,d)>1)
		{
			设gcd(a,x) = k;
			x = dk;
			gcd(a,dk) = k;
			设gcd(a,d)  = g;
			gcd(a/g,dk/g) = k/g;
			a/g和d/g互质
			所以gcd(a/g,k) = k/g
			k/gcd(a/g,k) = g;
			求f(a/g,g);
		}
*/
int f(int a,int d)
{
	int g = gcd(a,d);
	if(g==1)return 1;
	return f(a/g,g);
}
int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		int a,c;
		cin>>a>>c;
	
		if(c%a)cout<<"NO SOLUTION\n";
		else
		{
			int d = c/a;
			cout<<d*f(a,d)<<endl;
		}
	}	
	return 0;
}

法二:我们可以很容易知道答案一定是质数,因为如果是合数那我们一定可以消去一个约数找到更优的。

同样对于每个\(a,c\)\(c\bmod a \neq 0\)则无解,否则

\(lcm(a,b) = \dfrac{ab}{\gcd(a,b)}=c\)

\(\dfrac{b}{\gcd(a,b)} = \dfrac{c}{a}\) ,设\(b = \dfrac{c}{a}\),若\(\gcd(a,b)\neq 1\)就不断调整

理由如下:

\(b = \dfrac{c}{a}\)\(d = \gcd(a,b)\),若\(\gcd(a,b)\neq 1\),则就证明此时的\(a\)\(b的最小公倍数\)肯定不是\(c\),

而是\(\dfrac{ab}{d}\),那么我们通过\(a = \dfrac{a}{d}和b = b\times d\)进行调整,保证了\(\dfrac{ab}{gcd(a,b)}=c\)仍成立的同时消去一个公因子

不断调整直到\(d=1\),输出\(b\)就是答案

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b)
{
	return b?gcd(b,a%b):a;
}
void solve(ll a,ll c)
{
	ll b,d;
	if(c%a)
	{
		cout<<"NO SOLUTION\n";
		return;
	}
	b=c/a;
	d=gcd(a,b);
	while(d!=1)
	{
		a/=d;
		b*=d;
		//保证a*b/gcd(a,b)==c的同时去掉了一个公因子
		d=gcd(a,b);
	}
	cout<<b<<endl;
	return;
}

int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		ll a,c;
		cin>>a>>c;
		// if(c%a)cout<<"NO SOLUTION\n";
		// else
		// {
		// 	ll t = c/a;
		// 	cout<<"t = "<<t<<endl;
		// 	ll g = gcd(t,a);
		// 	cout<<"g = "<<g<<endl;
		// 	cout<<t*g<<endl;
		// }
		solve(a,c);
	}
	return 0;
}

法三:

根据之前 b 为 \(\dfrac{c}{a}\) 的倍数就可以循环枚举 \(b\) 判断是否满足$ b = \dfrac{c}{a} \times \gcd(a,b)$。

#include <bits/stdc++.h>
using namespace std;

int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        if(b % a) {printf("NO SOLUTION\n");continue;}
        int x = b / a;
        for(int i = x;i <= b;i += x)
        {
            int gcd = __gcd(a,i);
            if(gcd * x == i) {printf("%d\n",i);break;}
        }
    }   
    return 0;
}