首页 > 代码库 > [数学+dfs] ZOJ 3753 Simple Equation

[数学+dfs] ZOJ 3753 Simple Equation

题目链接:

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5176

Simple Equation

Time Limit: 2 Seconds      Memory Limit: 65536 KB

There are many Equations. Some are difficult to solve, for example: an xn + an-1 xn-1 + .. + a0 = 0.

In this problem, you are given a simple equation: AX + BY = XY. To simplify the problem, here ABXY are positive integers. Your task is to find the solution (X, Y) of this equation where X is not less than M. If there are multiple solutions, you should choose the solution with the minimal X + Y. If there are still ties, you should choose the solution with the minimalX.

Input

There are multiple test cases (about 3000). For each test case:

There is only one line contains three integers AB (1 <= AB <= 10 ^ 9) and M (1 <= M <= 10 ^ 18).

Output

For each test case, output X and Y. If there is no valid solution, output "No answer" instead.

Sample Input

1 1 2
1 1 3
3 4 8
3 4 9

Sample Output

2 2
No answer
8 6
10 5

Author: LIANG, Mingqiang
Source: ZOJ Monthly, January 2014
Submit    Status

题目意思:

给定A,B,M,求方程AX+BY=XY,要求X、Y为整数,且X要大于等于M,且满足X+Y尽可能小,如果再相同取X较小的。

解题思路:

原方程等价于(X-B)(Y-A)=XY

先用素数筛选法筛选出1000000内的所有质数。

然后将A、B分解质因数,并把相同的质因数合并,然后dfs,对每个质因数枚举分给第一部分的个数,然后剩余的全部给第二部分,然后结束时比较X+Y与之前保存的值,看是否要更新。

代码:

//#include<CSpreadSheet.h>

#include<iostream>
#include<cmath>
#include<cstdio>
#include<sstream>
#include<cstdlib>
#include<string>
#include<string.h>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<list>
#include<queue>
#include<ctime>
#include<bitset>
#include<cmath>
#define eps 1e-6
#define INF ((1LL)<<(60LL))
#define PI acos(-1.0)
#define ll __int64
#define LL long long
#define lson l,m,(rt<<1)
#define rson m+1,r,(rt<<1)|1
#define M 1000000007
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;

#define N 1000000
#define Maxn 1100000
int prime[Maxn],cnt;
bool isp[N+100];
map<LL,int>myp;
LL a,b,m,Max,ansa,ansb;
map<LL,int>::iterator it;

void init() //素数筛选法筛出1000000内的质因数
{
    cnt=0;

    for(int i=0;i<=N;i++)
        isp[i]=true;
    for(int i=2;i<=N;i++)
    {
        if(!isp[i])
            continue;
        prime[++cnt]=i;
        for(int j=i;j<=N;j+=i)
            isp[j]=false;
    }
    //printf("%d\n",cnt);
}

void get(LL cur) //分解质因数并合并
{
    for(int i=1;i<=cnt&&prime[i]*prime[i]<=cur;i++)
    {
        if(cur%prime[i]==0)
        {
            while(cur%prime[i]==0)
            {
                myp[prime[i]]++;
                cur/=prime[i];
            }
        }
    }
    if(cur!=1)
        myp[cur]++;
}
void dfs(LL aa,LL bb,map<LL,int>:: iterator cur) //对每个质因数枚举分给两部分的个数
{
    LL temp=cur->first;
    int tt=cur->second;
    //printf("aa:%lld bb:%lld temp:%lld tt:%d\n",aa,bb,temp,tt);
    //system("pause");

    if(cur==myp.end())
    {
        if(aa+b>=m)
        {
             //printf("sum:%lld max:%lld\n",aa+b+bb+a,Max);
            //system("pause");
            if(aa+b+bb+a<Max)
            {
                Max=aa+b+bb+a;
                ansa=aa+b;
                ansb=bb+a;
            }
            else if(aa+b+bb+a==Max&&aa+b<=ansa) //相等的情况下保存较小的x
            {
                ansa=aa+b;
                ansb=bb+a;
            }
        }
        return ;
    }
    for(int i=0;i<=tt;i++)
    {
        cur++;
        dfs(aa*(LL)pow(temp,i),bb*(LL)pow(temp,tt-i),cur);
        cur--;
    }
}
int main()
{
   //freopen("in.txt","r",stdin);
   //freopen("out.txt","w",stdout);

   init();
   while(~scanf("%lld%lld%lld",&a,&b,&m))
   {
       myp.clear();
       get(a);
       get(b);

       it=myp.begin();

       Max=INF;
       //printf("%lld\n",Max);
       dfs(1,1,it);
       if(Max==INF)
            printf("No answer\n");
       else
            printf("%lld %lld\n",ansa,ansb);

       //printf("%d\n",myp.size());
   }
   return 0;
}