poj2347 Equations 模拟+数学

确实是好题,但是不会写,用waterloo给的数据生成器才过得

term有两种
1:(符号)+常数+(x/y)
2: 操作符

将等式简化为
a1x + b1y + c1 = a2x + b2y + c2
a3x + b3y + c3 = a4x + b4y + c4

最后可化为 ax = by + c
if(a==0 && b==0 && c!=0) 无解
令=1或==1表示不为零

首先求y
a1x = b1y + c1
a2x = b2y + c2

这个地方不知道有没有更好的想法,没有的话只能枚举情况讨论

由于有些情况具有对称性,有些情况可以被剪掉,所以实际要讨论的情况不多


a1==1, a2==1的问题都可以通过消元转化为Py=Q
if(b1==0 && b2==0) y无解

a1=1 b1=1
a2=0 b2=0
x, y无解

a1=1 b1=0
a2=0 b2=1
转为Py=Q

a1=1 b1=1
a2=0 b2=1
转为Py=Q

a1=0 b1=1 
a2=0 b2=0
转为Py=Q

a1=0 b1=1 
a2=0 b2=1
若 c1*b2 != c2*b1,y无解
若 c1*b2 == c2*b1,转为Py=Q, P=b1, Q=-c1

虽然说枚举的时候很麻烦,但是只要把无解的情况提出来,剩下的就可以乱搞了

转化为Py=Q问题
P==0无解
gcd(P,Q)=g,y=(Q/g)/(P/g)


x同理

最后注意

1. 最后一个case后面不能有空行

2. 分母不能为负数

#include <iostream>
#include <cstdio>
#include <cstdio>
#include <cctype>
#include <cstring>
using namespace std;

int t;
char str1[200], str2[200];
int a1, b1, c1;
int a2, b2, c2;
int a3, b3, c3;
int a4, b4, c4;
int len1, len2;

bool issign(char x){
	return (x=='+'||x=='-');
}

void solveEqua(char* str, int l, int r, int& a, int& b, int& c)
{
	a = b = c = 0;
	int op = 1;
	for(int i=l; i<r; i++)
	{
		if(str[i]==' ') continue;

		int sign=1, val=1;
		bool first=1;
		while(str[i]!=' ' && i<r)
		{
			if(issign(str[i]) && str[i+1]==' ') //遇到操作符
				op = str[i]=='+'? 1 : -1;

			if(isdigit(str[i]))//term
			{
				if(first){
					val = str[i]-'0';
					if(i>0 && issign(str[i-1]))
						sign = str[i]=='+'? 1 : -1;
					else sign = 1;
					first = 0;
				}
				else val+=str[i]-'0';

				if(i+1==r || !isdigit(str[i+1]))
					first = 1;
				else val*=10;

				if(i+1==r || str[i+1]==' ')
					c += val*sign*op;
			}

			if(issign(str[i]) && (str[i+1]=='x' || str[i+1]=='y'))
				sign = str[i]=='+'? 1 : -1;

			if(str[i]=='x')
				a += val*sign*op;
			else if(str[i]=='y')
				b += val*sign*op;
			i++;
		}
	}
}

int findPos(char* str){
	for(int i=0; i<strlen(str); i++){
		if(str[i] == '='){
			return i;
		}
	}
	return -1;
}

int gcd(int a, int b){
	if(b==0)	return a;
	return gcd(b, a%b);
}

int lcm(int a, int b){
	return a*b/gcd(a, b);
}

void solve(int a1, int b1, int c1, int a2, int b2, int c2, int& P, int& Q){
	/*无解的情况*/
	if(a1==0 && b1==0 && c1!=0)	return ;
	if(a2==0 && b2==0 && c2!=0)	return ;

	if(!b1 && !b2) return;

	if((!a1 && !b1 && a2 && b2)
		||( a1 && b1 && !a2 && !b2))
		return;
	if(!a1 && !a2 && b1 && b2)
	{
		if(c1*b2 != c2*b1)	
			return;
		else{
			P=b1, Q=-c1;
			return;
		}
	}
	
	/*剩下的随便搞*/
	if(a1 && a2){
		int L = lcm(a1,a2);
		P = (b2*L/a2-b1*L/a1);
		Q = (c1*L/a1)-(c2*L/a2);
		return;
	}
	if(!a1 && b1){
		P = b1, Q = -c1; return;
	}
	if(!a2 && b2){
		P = b2, Q = -c2; return;
	}
}

void printAns(int P, int Q){
	if(P==0) puts("don't know");
	else{
		if(Q%P==0) printf("%d\n", Q/P);
		else{
			int g = gcd(P, Q);
			Q=Q/g; P=P/g;
			if(P<0)	Q=-Q, P=-P;
			printf("%d/%d\n", Q, P);
		}
	}
}

int main(){
//	freopen("a.txt", "r", stdin);
//	freopen("b.txt", "w", stdout);
	cin>>t;
	getchar();
	while(t--){
		gets(str1); len1 = strlen(str1);
		gets(str2); len2 = strlen(str2);

		int pos = findPos(str1);	
		solveEqua(str1, 0, pos, a1, b1, c1);
		solveEqua(str1, pos+1, len1, a2, b2, c2);

		pos = findPos(str2);
		solveEqua(str2, 0, pos, a3, b3, c3);
		solveEqua(str2, pos+1, len2, a4, b4, c4);

		/*P=0表示无解*/
		int P=0, Q=0;
		solve(b1-b2, a2-a1, c2-c1, 
			b3-b4, a4-a3, c4-c3, P, Q);
		printAns(P, Q);

		P=Q=0;
		solve(a1-a2, b2-b1, c2-c1,
			a3-a4, b4-b3, c4-c3, P, Q);
		printAns(P, Q);
		if(t!=0) puts("");
		getchar();
	}
	return 0;
}


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值