首页 > 代码库 > [数学+dfs] ZOJ 3753 Simple Equation
[数学+dfs] ZOJ 3753 Simple Equation
题目链接:
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5176
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 A, B, X, Y 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 A, B (1 <= A, B <= 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
题目意思:
给定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; }