(原创题)解方程(数学+模拟)

xiaoxiao2021-02-28  78

Problem Description

解三元一次方程组。

Input 第一行输入一个整数T,表示数据组数(1< T< 10000); 对于每组数据,分三行输入,每一行输入一个字符串。 其中,字符串的输入标准格式为:ax + by + cz = d (d后面和a前面都没有空格,并且当字母系数的绝对值为1的时候系数可以省略不写); 保证数据合法,并且保证对于每一行的四个数据a、b、c、d的绝对值都小于100,a、b、c都不为会0。

Output 对于每组数据,如果x,y,z有且只有一个解,请输出x、y、z的最简分数形式的结果(具体格式请参照案例);如果x,y,z或有多个解,请在其后面输出inf;如果x,y,z无解,请在后面输出no。

Sample Input 1 3x + 2y + z = 10 x + 3y + 2z = 13 2x + y + 5z = 19

Sample Output x=1 y=2 z=3

这个是我无意间就想到的一个题目,意在考察模拟和数学能力,不过在自己验的时候却花费了很多功夫。

#include<iostream> #include<cstring> #include<cstdio> #include<cmath> using namespace std; int x[5],y[5],z[5],d[5]; int xx[5],yy[5],dd[5]; int xxx[5],ddd[5]; int px[5],py[5],pz[5]; int gcd(int a,int b) { return a%b==0?b:gcd(b,a%b); } int get(char s[]) //把字符前的系数提出来 { int len=strlen(s),j=1,sum=0; if(len==1) return 1; if(len==2&&s[0]=='-') return -1; for(int i=len-2;i>0;i--,j*=10) sum+=(s[i]-'0')*j; if(s[0]!='-') sum+=(s[0]-'0')*j; else sum=-sum; return sum; } void copy(int i,int j) { int p=((z[i]*z[j])>0)?(-1):1; //判断要消去的变量z前面系数是否同号 xx[i]=p*x[i];yy[i]=p*y[i];dd[i]=p*d[i]; //如果同号 就把第一组方程所有系数都乘以-1 否则乘以1 用变量p控制 xx[j]=x[j];yy[j]=y[j];dd[j]=d[j]; } void guess(int i,int j,int m) //消元 ==> 三元消成二元 { for(int k=i;k<=j;k++) { xx[k]*=m/abs(z[k]); yy[k]*=m/abs(z[k]); dd[k]*=m/abs(z[k]); } xx[i]+=xx[j];yy[i]+=yy[j];dd[i]+=dd[j]; } void print(int x,int y) //打印输出 { if(x==0) { cout<<0; return ; } int blag=(x*y<0)?1:0; x=abs(x),y=abs(y); if(blag) cout<<"-"; if(x%y==0) cout<<x/y; else if(y%x==0) cout<<"1"<<"/"<<y/x; else { int m=gcd(x,y); cout<<x/m<<"/"<<y/m; } } int main() { int t; cin>>t; while(t--) { char k,s1[10],s2[10],s3[10]; for(int i=0;i<3;i++) //将三元一次方程组存入x级中 { scanf("%s %c %s %c %s %c %d",s1,&k,s2,&k,s3,&k,&d[i]); x[i]=get(s1); y[i]=get(s2); z[i]=get(s3); } for(int i=0;i<2;i++) //同时需要联立1、2和2、3两组方程组并且作消元处理 得到一个二元一次方程组 存入xx级中 { int m=abs(z[i])*abs(z[i+1]); copy(i,i+1); guess(i,i+1,m); } if(yy[0]==0||yy[1]==0) { if(yy[0]==0) { px[0]=dd[0]; px[1]=xx[0]; py[0]=dd[1]*px[1]-xx[1]*px[0]; py[1]=px[1]*yy[1]; } else { px[0]=dd[1]; px[1]=xx[1]; py[0]=dd[0]*px[1]-xx[0]*px[0]; py[1]=px[1]*yy[0]; } pz[0]=d[0]*px[1]*py[1]-x[0]*px[0]*py[1]-y[0]*py[0]*px[1]; pz[1]=px[1]*py[1]*z[0]; } else { int m=abs(yy[0])*abs(yy[1]),p=((yy[0]*yy[1])>0)?(-1):1; xxx[0]=p*xx[0];ddd[0]=p*dd[0]; xxx[1]=xx[1];ddd[1]=dd[1]; for(int i=0;i<2;i++) { xxx[i]*=m/abs(yy[i]); ddd[i]*=m/abs(yy[i]); } xxx[0]+=xxx[1];ddd[0]+=ddd[1]; //联立二元一次方程组 继续消元 得到一个关于x的一元一次的方程 存入xxx级中 if(xxx[0]) { px[0]=ddd[0]; px[1]=xxx[0]; // xx[0]*(px[0]/px[1])+yy[0]*y=dd[0] ==> y=(dd[0]*px[1]-px[0]*xx[0])/(px[1]*yy[0]) py[0]=dd[0]*px[1]-xx[0]*px[0]; py[1]=px[1]*yy[0]; //x[0]*(px[0]/px[1])+y[0]*(py[0]/py[1])+z[0]*z=d ==> (x[0]*px[0]*py[1]+y[0]*py[0]*px[1])/(px[1]*py[1])+z[0]*z=d pz[0]=d[0]*px[1]*py[1]-x[0]*px[0]*py[1]-y[0]*py[0]*px[1]; pz[1]=px[1]*py[1]*z[0]; } else { px[0]=0; py[0]=dd[0]; py[1]=yy[0]; // y[0]*(py[0]/py[1])+z[0]*z=d[0] ==> z=(d[0]*py[1]-py[0]*y[0])/(py[1]*z[0]) pz[0]=d[0]*py[1]-y[0]*py[0]; pz[1]=py[1]*z[0]; } } cout<<"x=";print(px[0],px[1]); cout<<" y=";print(py[0],py[1]); cout<<" z=";print(pz[0],pz[1]); cout<<endl; } return 0; }
转载请注明原文地址: https://www.6miu.com/read-32554.html

最新回复(0)