版权声明:本文为博主原创文章,转载请注明出处。 https://blog.csdn.net/sdau20163942/article/details/82934070
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5974
题意:给出a和b,让找到X和Y满足:
- X+Y=a;
- LCM(X,Y)=b;
LCM为最小公倍数,(1≤a≤2*10^4),(1≤b≤10^9),注意:测试样例很多。
解析:
- 首先考虑lcm的性质,假设有等式lcm(a,b)=x;
- 将x分解质因数得:x=p1^num1*p2^num2...*pk^numk。
- 将a分解质因数得:a=p1^numa1*p2^numa2...*pk^numak。
- 将b分解质因数得:b=p1^numb1*p2^numb2...*pk^numbk。
- 则num1=max(numa1,numb1),num2=max(numa2,numb2)...numk=max(numak,numbk)
- 注意:a,b与x分解的质因子相同是因为,a和b的质因子也一定是x的质因子,而如果x的某个质因子pi如果不是a的质因子,只需使得a等式中的pi的幂为0即可。
所以这里知道了b之后就有了一种枚举X与Y的方式:
将X看做k项相乘,即X=[p1^0或p1^2...或p1^num1]*[p2^0或p2^2...或p2^num1]...*[pk^0或pk^2...或pk^num1],然后怎么得到对应的Y使得LCM(X,Y)=b呢?
- 这里枚举到X的第i项为pi^tx,假设Y的第i项为pi^ty.
- 如果tx<numi那么由于max(tx,ty)=numi,那么ty=numi;
- 如果tx==numi那么由于max(tx,ty)=numi,那么ty取值范围为0~numi。
综上dfs枚举X,Y判断是否等于a即可。但是上述方法复杂度是比较高的,看别的题解上都是推了个公式解一下来直接求的X,Y,时间用的会少一些。
最后注意题目中的超级大天坑:最后输出的X,Y一定保证小的在前。这一点比赛时卡了我一个多小时,TMD。
代码(719ms):
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
bool flag;
ll a,b,len,ansx,ansy;
ll p[105],num[105];
void init(ll n)//分解质因子
{
len=0;
for(ll i=2;i*i<=n;i++)
{
if(n%i==0)
{
p[++len]=i;
num[len]=0;
}
while(n%i==0)
{
num[len]++;
n=n/i;
}
}
if(n>1)
{
p[++len]=n;num[len]=1;
}
}
ll fpow(ll n,ll x)//求n^x
{
ll ans=1;
for(int i=1;i<=x;i++)
ans=ans*n;
return ans;
}
//step是当前处理到第step个因子,sum1是X前step-1项的累乘,sum2是Y前step-1项的累乘
void dfs(ll step,ll sum1,ll sum2)
{
//x的第step项取p[step]^i,此时Y的第step 项一定是p[step]^num[step]
for(int i=0;i<num[step];i++)
{
if(flag) return;
if(step<len)
{
dfs(step+1,sum1*fpow(p[step],i),sum2*fpow(p[step],num[step]));
}
else
{
ll x=sum1*fpow(p[step],i);
ll y=sum2*fpow(p[step],num[step]);
//cout<<x<<" "<<y<<endl;
if(x+y==a)
{
flag=true;
ansx=x;ansy=y;
return;
}
}
}
//x的第step项固定取p[step]^num[step],然后枚举Y的第step项
for(int i=0;i<=num[step];i++)
{
if(flag) return;
if(step<len)
{
dfs(step+1,sum1*fpow(p[step],num[step]),sum2*fpow(p[step],i));
}
else
{
ll x=sum1*fpow(p[step],num[step]);
ll y=sum2*fpow(p[step],i);
//cout<<x<<" "<<y<<endl;
if(x+y==a)
{
flag=true;
ansx=x;ansy=y;
return;
}
}
}
}
int main()
{
while(scanf("%lld%lld",&a,&b)!=EOF)
{
if(a==1)
{
printf("No Solution\n");
continue;
}
if(b==1)
{
if(a==2)
printf("1 1\n");
else
printf("No Solution\n");
continue;
}
init(b);
flag=false;
dfs(1ll,1ll,1ll);
if(flag)
{
if(ansx>ansy) swap(ansx,ansy);
printf("%lld %lld\n",ansx,ansy);
}
else
printf("No Solution\n");
}
return 0;
}