ZOJ 3753 Simple Equation

[题意]让你解这样一个方程:AX+BY=XY。给定A、B(1<=A,B<=10^9)和M,其中A>=M。让你求X和Y(X,Y>0),其中要求X+Y尽可能小,X尽可能小(优先级递减)。

[分析]将方程变形,可以得到结果:(X-B)(Y-A)=AB。再考虑到X和Y均为正整数,X>=M,问题就转化为分解A和B。

WA了好多次,在将A和B的质因数进行合并的时候出现了问题,我简直是太渣了。。。

#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;

#define Zero(v) memset(v, 0, sizeof(v))
typedef long long lld;

const int maxn = 100010;
const int MAX = 5555;
const int INF = 1000000000;

int fac1[100], fac2[100];
int ret1[100], ret2[100];
int fac[100], ret[100]; 
int prime[maxn];
int tot;
bool mk[maxn], OK;
lld ansX, ansY;


void init() {
	Zero(mk);
	for(int i=2; i*i<maxn; i++) {
		if(!mk[i]) {
			for(int j=i*i; j<maxn; j+=i) mk[j] = 1;
		}
	}
	tot = 0;
	for(int i=2; i<maxn; i++) {
		if(!mk[i]) prime[tot++] = i;
	}
}

void split(lld n, int* fac, int* ret, int &cnt) {
	lld m = n;
	for(int i=0; i<tot && prime[i]*prime[i]<=n; i++) {
		if(m%prime[i] == 0) {
			int tmp = 0;
			fac[cnt] = prime[i];
			while(m%prime[i] == 0) {
				m /= prime[i];
				tmp ++;
			}
			ret[cnt++] = tmp;
		}
	}
	if(m > 1) fac[cnt] = m, ret[cnt++] = 1;	
}

lld modPow(int n, int m) {
	lld ret = 1;
	for(; m; m>>=1, n=n*n) {
		if(m&1) ret *= n;
	}
	return ret;
}

void dfs(lld A, lld B, lld M, lld cur, int step, int cnt) {
	if(step == cnt) {
		lld X = cur + B;
		lld Y = A*B/cur + A;
		if(X >= M) {
			if(!OK) {
				ansX = X;
				ansY = Y;
			}
			OK = true;
			if(X+Y < ansX+ansY) {
				ansX = X;
				ansY = Y;
			} else if(X+Y == ansX+ansY) {
				if(X < ansX) {
					ansX = X;
					ansY = Y;
				}
			}
		}
		return ;
	}
	for(int i=0; i<=ret[step]; i++) {
		dfs(A, B, M, cur*modPow(fac[step], i), step+1, cnt);
	}
}

void gao(lld A, lld B, lld M) {
	int cnt1 = 0, cnt2 = 0;
	split(A, fac1, ret1, cnt1);
	split(B, fac2, ret2, cnt2);

	int cnt = 0;
	fac[cnt] = 1;
	ret[cnt++] = 1;
	int i = 0, j = 0;

	while(i < cnt1 || j < cnt2) {
		if(i >= cnt1 && j >= cnt2) break;
		if(i >= cnt1) {
			fac[cnt] = fac2[j];
			ret[cnt] = ret2[j];
			cnt++; j++;
			if(j >= cnt2) break;
			continue;
		}
		if(j >= cnt2) {
			fac[cnt] = fac1[i];
			ret[cnt] = ret1[i];
			cnt++; i++;
			if(i >= cnt1) break;
			continue;
		}
		if(fac1[i] > fac2[j]) {
			fac[cnt] = fac2[j];
			ret[cnt] = ret2[j];
			cnt++; j++;
			continue;
		}
		if(fac1[i] < fac2[j]) {
			fac[cnt] = fac1[i];
			ret[cnt] = ret1[i];
			cnt++; i++;
			continue;
		}
		if(fac1[i] == fac2[j]) {
			fac[cnt] = fac1[i];
			ret[cnt] = ret1[i] + ret2[j];
			cnt++; i++; j++;
			continue;
		}
	}

	//while(i < cnt1 || j < cnt2) {
	//	if((i<cnt1 && j<cnt2 && fac1[i]<fac2[j]) || (j==cnt2 && i<cnt1)) {
	//		fac[cnt] = fac1[i];
	//		ret[cnt] = ret1[i];
	//		cnt++; i++;
	//	}
	//	else if((i<cnt1 && j<cnt2 && fac1[i]>fac2[j]) || (i==cnt1 && j<cnt2)) { 
	//		fac[cnt] = fac2[j];
	//		ret[cnt] = ret2[j];
	//		cnt++; j++;
	//	}
	//	else if(i<cnt1 && j<cnt2 && fac1[i]==fac2[j]) {
	//		fac[cnt] = fac1[i];
	//		ret[cnt] = ret1[i] + ret2[j];
	//		cnt++; i++; j++;
	//	}

	//}

	OK = false;
	dfs(A, B, M, 1, 0, cnt);
	if(OK) printf("%lld %lld\n", ansX, ansY);
	else puts("No answer");
}


int main() {
	lld A, B, M;

	init();
	while(scanf("%lld%lld%lld", &A, &B, &M) != EOF) {
		gao(A, B, M);
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值