HDU5974 - The 2016 ACM-ICPC Asia Dalian Regional Contest - D - A Simple Math Problem - (数论LCM,dfs)

版权声明:本文为博主原创文章,转载请注明出处。 https://blog.csdn.net/sdau20163942/article/details/82934070

题目链接http://acm.hdu.edu.cn/showproblem.php?pid=5974

题意:给出a和b,让找到X和Y满足:

  1. X+Y=a;
  2. 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;
}

猜你喜欢

转载自blog.csdn.net/sdau20163942/article/details/82934070
今日推荐