HDU2449 Gauss Elimination 高斯消元 高精度 (C++ AC代码)

时间:2021-06-24 15:55:35

原文链接https://www.cnblogs.com/zhouzhendong/p/HDU2449.html

题目传送门 - HDU2449

题意

  高精度高斯消元。

  输入 $n$ 个 $n$ 元方程。

  $n\leq 100$

  注:本题对输入数值大小貌似没有说明限制。

题解

  高精度高斯消元啊,去写。去写。写写写写写写写写写写写写写写写写写写!!

  然后就可以写出来了。

  下面讲故事。

  那是 2017 年 7 月。

  呀!高精度高斯消元裸题!

  当时还不会 FFT 。

  去年暑假花了一个星期的零碎时间搞了一个高精度板子。

  然后大概是过了某网站的 “高精度加法,高精度乘法,高精度除法,高精度减法” 等等。

  自以为板子绝对没问题了。

  然后手写高精度分数类。

  手写高斯消元。

  然后是 WA 和 TLE 。

  于是我以为是没用 FFT 导致超时。

  于是那年,那天,我弃疗了。

  前几天,我在和某大佬谈“毒瘤题”的时候,突然想起这个问题了。

  我记得我当时是这样向他描述这一题的:高精度高斯消元,还卡时间,要加 FFT 。

  也是在前几天,我把这个求 HDU2449 AC代码的问题发到某著名“新人求助”论坛上。

  得到了非常专业的回答:当时 ICPC 的时候大家几乎都是用 java 写的。(大概是这样的)

  的确非常有道理。

  网上也是 java 的代码一片一片互相"借鉴"。

  但是我在那天便有个想法:我已经会 FFT 了。我也许可以再试试。

  今天,我还没开始打 FFT 。还没有把之前的 $O(n^2)$ 乘法删掉。

  我想了想:拆系数 FFT 的常数巨大。本题,光 $n$ 贡献的复杂度就有 $O(n^3)$ ,可以占领 $1000000$ 的复杂度,留给高精度的复杂度不多,所以数字一定不会很大。于是我意识到乘法效率可能不是重点。

  然而好像还是只能打 FFT 。

  正当我要删乘法函数的时候,我意识到:9 位压位啊,如果我用我惯用的高精度乘法,会炸 $long\ long$ ,当时是否看到了这个问题?

  于是我一检查,发现我当时顺手写了进位。

  然后我发现我把 $j$ 打成了 $1$ 。

  ……

  HDU2449 Gauss Elimination 高斯消元 高精度 (C++ AC代码)

  看到这个东西的时候,我感动极了。

  好久没有碰语文了。似乎我写不出什么有文采的东西了。见笑了。

  注:今天之前的上一次提交是在 2017-07-19 。为此,我准备了大约一个星期的高精度板子。所以,上一次面对这题大概是 7 月 12 日左右吧。

  高精度高消??

如果您在我初三时还不认识我,您不需要看这段文字。

  穿越一年的时光,风,仍是风;云,还是云。

  偶然的,我揭开了尘封的记忆,遇见了当年的代码。

  当年,我究竟是如何有勇气写下这份代码?

  而当年,又是什么,让我侥幸尘封了这段记忆?

  每一次,遇见过去的点点滴滴;每一次,在点点滴滴中,遇见当年的我和他们。(上一次遇见 -> https://www.cnblogs.com/zhouzhendong/p/NOIP2017Day2T2.html)

  而这,又是一次黯然神伤。

  即使当前是一片彩虹,瞬间地,也可能来一场暴风雨,刷洗罢,却不还来彩虹。

  忘了吧!

  又怎能忘?那些故事,曾塞满了当年时空中的空隙,又时不时的出现。

  这一年,是疲惫的一年。太多的人和事,太多的彷徨。

  是的,失去了,便开始恋恋不舍了。

  珍惜当下,把握今天。

注:以下这段话,也许只有 Emoairx 和 Chunlvxiong 才能特别看懂。

  

代码

  下面放两份代码。第一份是我今天的 AC 代码。一份是我一年前的 TLE 代码。有兴趣的同学可以找不同。是个低级错误。

#pragma comment(linker, "/STACK:102400000,102400000")
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
using namespace std;
typedef long long LL;
/*
大数模板8
1. 支持大数之间的+、-、*、/、%运算,以及一些基础的计算
2. 支持部分大数与整型之间的运算 (仅限于大数在前整型在后) +、-、*、/、%
3. 支持负数的运算,不会出现减法的时候由于被减数小于减数所造成的报错。
4. 快速幂,代码优化
5. 可以进行正常的比较。
6. 新增 abs(), read()两个方便的函数
read() 具体用法
1. read('c',Var_Name<BigInt>) 读入一个char数组类型转化而来的大数
2. read('i',Var_Name<BigInt>) 读入一个int类型转化而来的大数
3. read('L',Var_Name<BigInt>) 读入一个long long类型转化而来的大数
7. 修复原先模板中关于0的bug
8. 新增构造函数
9. 修复若干bug,新增一些功能
10. progress: 9位压位,大大提高效率
*///版权所有--周镇东
const int MaxLen=4200;
const LL mod=1e9;
const LL Pow10[9]={1e0,1e1,1e2,1e3,1e4,1e5,1e6,1e7,1e8};
struct BigInt{
LL d,v[MaxLen+5];
bool f;//保存正负性 ,0当作正数看待
BigInt (){}
BigInt (LL x){(*this)=x;}
BigInt (int x){(*this)=x;}
BigInt (char x[]){(*this)=x;}
BigInt (const BigInt &x){(*this)=x;}
void Print(){
if (f)
putchar('-');
if (d==0){
putchar('0');
return;
}
printf("%lld",v[d]);
for (int i=d-1;i>=1;i--)
printf("%09lld",v[i]);
}
void Print(char c){//输出数字
(*this).Print();
printf("%c",c);
}
void ya(){
LL v_[MaxLen];
memset(v_,0,sizeof v_);
for (int i=1;i<=d;i++)
v_[(i-1)/9+1]+=Pow10[(i-1)%9]*v[i];
d=(d-1)/9+1;
memset(v,0,sizeof v);
for (int i=1;i<=d;i++)
v[i]=v_[i];
while (d>0&&v[d]==0)
d--;
}
void operator =(char x[]){
f=x[0]=='-',d=strlen(x)-f,memset(v,0,sizeof v);
for (int i=f;i<d+f;i++)
v[i-f+1]+=(x[d+f-(i-f)-1]-48);
while (d>0&&v[d]==0)
d--;
(*this).ya();
}
void operator =(int x){
(*this)=(LL)x;
}
void operator =(LL x){
d=0,f=x<0,x=abs(x);
memset(v,0,sizeof v);
while (x)
v[++d]=x%mod,x/=mod;
}
bool equ(BigInt &x){//cmp abs
if (d!=x.d)
return 0;
for (int i=1;i<=d;i++)
if (v[i]!=x.v[i])
return 0;
return 1;
}
bool operator ==(BigInt &x){//cmp abs
if (f!=x.f)
return 0;
return (*this).equ(x);
}
bool nequ(BigInt &x){
return !(*this).equ(x);
}
bool operator !=(BigInt &x){
return !(*this==x);
}
bool smaller(BigInt &x){
if (d!=x.d)
return d<x.d;
for (int i=d;i>=1;i--)
if (v[i]!=x.v[i])
return v[i]<x.v[i];
return 0;
}
bool bigger(BigInt &x){
if (d!=x.d)
return d>x.d;
for (int i=d;i>=1;i--)
if (v[i]!=x.v[i])
return v[i]>x.v[i];
return 0;
}
bool operator <(BigInt &x){//cmp abs
if (f!=x.f)
return f;
if (f&&x.f)
return (*this).bigger(x);
return (*this).smaller(x);
}
bool operator >(BigInt &x){
if (f!=x.f)
return x.f;
if (f&&x.f)
return (*this).smaller(x);
return (*this).bigger(x);
}
bool smqu(BigInt &x){
return !(*this).bigger(x);
}
bool bgqu(BigInt &x){
return !(*this).smaller(x);
}
bool operator <=(BigInt &x){
return !(*this>x);
}
bool operator >=(BigInt &x){
return !(*this<x);
}
BigInt operator +(BigInt x){//加法运算
BigInt Ans=*this;
if (f!=x.f){
Ans.f=x.f=0;
if (f)
return x-Ans;
else
return Ans-x;
}
memset(Ans.v,0,sizeof Ans.v);
Ans.f=f,Ans.d=max(d,x.d);
for (int i=1;i<=Ans.d;i++)
Ans.v[i]=v[i]+x.v[i];
for (int i=1;i<=Ans.d;i++)
Ans.v[i+1]+=Ans.v[i]/mod,Ans.v[i]%=mod;
if (Ans.v[Ans.d+1])
Ans.d++;
if (Ans.d==0)
Ans.f=0;
return Ans;
}
BigInt operator +(const LL x){
BigInt X(x);
return X+(*this);
}
BigInt operator -(BigInt y){//减法运算
BigInt Ans=*this;
if (f!=y.f){
y.f=Ans.f,Ans=Ans+y;
return Ans;
}
if (Ans.equ(y)){
Ans=0;
return Ans;
}
if (Ans.smaller(y)){
Ans=y-Ans,Ans.f=!f;
return Ans;
}
for (int i=1;i<=max(Ans.d,y.d);i++)
if (Ans.v[i]-y.v[i]<0)
Ans.v[i]+=mod-y.v[i],Ans.v[i+1]--;
else
Ans.v[i]-=y.v[i];
while (Ans.d>0&&Ans.v[Ans.d]==0)
Ans.d--;
if (Ans.d==0)
Ans.f=0;
return Ans;
}
BigInt operator -(const LL x){
BigInt Ans(x);
return (*this)-Ans;
}
BigInt operator *(const BigInt &y){//乘法运算
BigInt x=*this,Ans(0);
Ans=0,Ans.f=f^y.f;
for (int i=1;i<=x.d;i++)
for (int j=1;j<=y.d;j++){
LL now=Ans.v[i+j-1]+x.v[i]*y.v[j];
Ans.v[i+j-1]=now%mod;
Ans.v[i+j]+=now/mod;
}
Ans.d=x.d+y.d-1;
for (int i=1;i<=Ans.d;i++)
Ans.v[i+1]+=Ans.v[i]/mod,Ans.v[i]%=mod;
if (Ans.v[Ans.d+1])
Ans.d++;
if (Ans.d==0)
Ans.f=0;
return Ans;
}
BigInt operator *(LL y){
BigInt Ans=*this;
if (y<0)
Ans.f^=1;
y=abs(y);
for (int i=1;i<=d;i++)
Ans.v[i]*=y;
for (int i=1;i<=d||Ans.v[i]>0;i++)
Ans.v[i+1]+=Ans.v[i]/mod,Ans.v[i]%=mod,Ans.d=max(d,i);
if (Ans.d==0)
Ans.f=0;
return Ans;
}
BigInt operator /(BigInt y){//除法运算
BigInt Ans(0),x=*this,minus;
bool Ansf=f^y.f;
x.f=y.f=0,minus=y;
while ((minus*10).smqu(x))
minus=minus*10;
while (minus.bgqu(y)){
Ans=Ans*10;
while (minus.smqu(x))
x=x-minus,Ans=Ans+1;
minus=minus/10;
}
Ans.f=Ansf;
if (Ans.d==0)
Ans.f=0;
return Ans;
}
BigInt operator /(LL x){
BigInt Ans(0);
LL prev=0;
Ans.f=f^(x<0),Ans.d=0,x=abs(x);
for (int i=d;i>0;i--){
prev=prev*mod+v[i];
if (prev>=x)
Ans.v[i]=prev/x,prev%=x,Ans.d=max(Ans.d,i);
}
if (Ans.d==0)
Ans.f=0;
return Ans;
}
BigInt operator %(BigInt y){//取模运算
BigInt x=*this,minus;
bool xfz=f^y.f;
x.f=y.f=0,minus=y;
if (x<y){
x.f=xfz;
return x;
}
while ((minus*10).smqu(x))
minus=minus*10;
while (minus.bgqu(y)){
while (minus.smqu(x))
x=x-minus;
minus=minus/10;
}
x.f=xfz;
if (x.d==0)
x.f=0;
return x;
}
LL operator %(LL x){
LL prev=0;
bool flag=f^(x<0);
x=abs(x);
for (int i=d;i>0;i--)
prev=prev*mod+v[i],prev%=x;
if (flag)
prev=-prev;
return prev;
}
BigInt operator ^(int x){
BigInt Ans;
Ans=1;
if (x==0)
return Ans;
Ans=*this^(x/2);
Ans=Ans*Ans;
if (x&1)
Ans=Ans**this;
return Ans;
}
}zero(0),one(1);
BigInt GcdY(BigInt x,BigInt y){
BigInt z;
while (y!=zero){
z=y;
y=x%y;
x=z;
}
return x;
}
BigInt Gcd(BigInt x,BigInt y){
x.f=y.f=0;
if (x==zero)
return y;
if (y==zero)
return x;
return GcdY(x,y);
}
BigInt LcmY(BigInt x,BigInt y){
return x/GcdY(x,y)*y;
}
BigInt Lcm(BigInt x,BigInt y){
x.f=y.f=0;
if (x==zero)
return y;
if (y==zero)
return x;
return LcmY(x,y);
}
BigInt abs(BigInt x){
x.f=0;
return x;
}
void read(char ch,BigInt &x){
if (ch=='c'){
char str[MaxLen];
scanf("%s",str),x=str;
}
if (ch=='i'){
int y;
scanf("%d",&y),x=y;
}
if (ch=='L'){
LL y;
scanf("%lld",&y),x=y;
}
}
void readint(BigInt &x,int &ret){
scanf("%d",&ret),x=ret;
}
void readLL(BigInt &x,LL &ret){
scanf("%lld",&ret),x=ret;
}
// var board
const int N=100+5;
int n;
BigInt a[N][N];
struct BigDouble{
BigInt a,b;
void Print(){
(*this).Smaller();
if (a==zero){
printf("0");
return;
}
if (b==one)
a.Print();
else
a.Print('/'),b.Print();
}
void Print(char ch){
(*this).Smaller();
if (a==zero){
printf("0%c",ch);
return;
}
if (b==one)
a.Print(ch);
else
a.Print('/'),b.Print(ch);
}
void Smaller(){
if (a==zero||b==zero)
return;
// a.Print('\n');b.Print('\n');
BigInt gcd=Gcd(a,b);
// puts("Small achieve");
a=a/gcd,b=b/gcd;
// puts("div adchive");
if (b.f)
a.f^=1,b.f^=1;
}
void operator = (BigInt x){
a=x,b=one;
}
BigDouble operator * (BigDouble x){
BigDouble ans;
ans.a=a*x.a,ans.b=b*x.b;
ans.Smaller();
return ans;
}
BigDouble operator * (BigInt x){
BigDouble ans;
ans.a=x*a,ans.b=b;
ans.Smaller();
return ans;
}
BigDouble operator - (BigDouble x){
BigDouble ans;
BigInt lcm=Lcm(b,x.b),tt=lcm/b,tx=lcm/x.b;
// BigInt lcm=one,tt=one,tx=one;
ans.b=lcm,ans.a=a*tt-x.a*tx;
ans.Smaller();
return ans;
}
BigDouble operator / (BigInt x){
BigDouble ans;
// b.Print('\n');x.Print('\n');
ans.a=a,ans.b=b*x;
// puts("still alive");
ans.Smaller();
return ans;
}
BigDouble operator / (BigDouble x){
BigDouble ans;
ans.a=a*x.b,ans.b=b*x.a;
ans.Smaller();
return ans;
}
}x[N];
// var board
void Debug(){
for (int i=0;i<n;i++){
for (int j=0;j<=n;j++)
a[i][j].Print(' ');
puts("");
}
}
bool Gauss(){
int k,c;
for (k=c=0;k<n&&c<n;k++,c++){
int Mk;
for (Mk=k;Mk<n&&a[Mk][c]==zero;Mk++);
if (Mk>=n)
return 0;
if (Mk!=k)
for (int i=c;i<=n;i++)
swap(a[k][i],a[Mk][i]);
for (int i=k+1;i<n;i++)
if (a[i][c]!=zero){
BigInt lcm=Lcm(a[i][c],a[k][c]);
BigInt ta=lcm/a[i][c],tb=lcm/a[k][c];
for (int j=c;j<=n;j++)
a[i][j]=a[i][j]*ta-a[k][j]*tb;
}
// Debug();
}
for (int i=n-1;i>=0;i--){
BigDouble tmp;
tmp=a[i][n];
for (int j=i+1;j<n;j++){
// x[j].Print('\n');
// a[i][j].Print('\n');
// tmp.Print('\n');
tmp=tmp-x[j]*a[i][j];
}
// x[i].Print('\n'),tmp.Print('\n'),a[i][i].Print('\n');
x[i]=tmp/a[i][i];
}
return 1;
}
int main(){
while (~scanf("%d",&n)){
for (int i=0;i<n;i++)
for (int j=0;j<=n;j++)
read('c',a[i][j]);
for (int i=0;i<n;i++){
BigInt GCD=zero;
for (int j=0;j<=n;j++)
if (a[i][j]!=zero){
if (GCD==zero)
GCD=a[i][j];
else
GCD=Gcd(GCD,a[i][j]);
}
if (GCD!=zero)
for (int j=0;j<=n;j++)
a[i][j]=a[i][j]/GCD;
}
// Debug();
// Gauss();continue;
if (Gauss())
for (int i=0;i<n;i++)
x[i].Print('\n');
else
puts("No solution.");
puts("");
}
return 0;
}
#pragma comment(linker, "/STACK:102400000,102400000")
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
using namespace std;
typedef long long LL;
/*
大数模板8
1. 支持大数之间的+、-、*、/、%运算,以及一些基础的计算
2. 支持部分大数与整型之间的运算 (仅限于大数在前整型在后) +、-、*、/、%
3. 支持负数的运算,不会出现减法的时候由于被减数小于减数所造成的报错。
4. 快速幂,代码优化
5. 可以进行正常的比较。
6. 新增 abs(), read()两个方便的函数
read() 具体用法
1. read('c',Var_Name<BigInt>) 读入一个char数组类型转化而来的大数
2. read('i',Var_Name<BigInt>) 读入一个int类型转化而来的大数
3. read('L',Var_Name<BigInt>) 读入一个long long类型转化而来的大数
7. 修复原先模板中关于0的bug
8. 新增构造函数
9. 修复若干bug,新增一些功能
10. progress: 9位压位,大大提高效率
*///版权所有--周镇东
const int MaxLen=4200;
const LL mod=1e9;
const LL Pow10[9]={1e0,1e1,1e2,1e3,1e4,1e5,1e6,1e7,1e8};
struct BigInt{
LL d,v[MaxLen+5];
bool f;//保存正负性 ,0当作正数看待
BigInt (){}
BigInt (LL x){(*this)=x;}
BigInt (int x){(*this)=x;}
BigInt (char x[]){(*this)=x;}
BigInt (const BigInt &x){(*this)=x;}
void Print(){
if (f)
putchar('-');
if (d==0){
putchar('0');
return;
}
printf("%lld",v[d]);
for (int i=d-1;i>=1;i--)
printf("%09lld",v[i]);
}
void Print(char c){//输出数字
(*this).Print();
printf("%c",c);
}
void ya(){
LL v_[MaxLen];
memset(v_,0,sizeof v_);
for (int i=1;i<=d;i++)
v_[(i-1)/9+1]+=Pow10[(i-1)%9]*v[i];
d=(d-1)/9+1;
memset(v,0,sizeof v);
for (int i=1;i<=d;i++)
v[i]=v_[i];
while (d>0&&v[d]==0)
d--;
}
void operator =(char x[]){
f=x[0]=='-',d=strlen(x)-f,memset(v,0,sizeof v);
for (int i=f;i<d+f;i++)
v[i-f+1]+=(x[d+f-(i-f)-1]-48);
while (d>0&&v[d]==0)
d--;
(*this).ya();
}
void operator =(int x){
(*this)=(LL)x;
}
void operator =(LL x){
d=0,f=x<0,x=abs(x);
memset(v,0,sizeof v);
while (x)
v[++d]=x%mod,x/=mod;
}
bool equ(BigInt &x){//cmp abs
if (d!=x.d)
return 0;
for (int i=1;i<=d;i++)
if (v[i]!=x.v[i])
return 0;
return 1;
}
bool operator ==(BigInt &x){//cmp abs
if (f!=x.f)
return 0;
return (*this).equ(x);
}
bool nequ(BigInt &x){
return !(*this).equ(x);
}
bool operator !=(BigInt &x){
return !(*this==x);
}
bool smaller(BigInt &x){
if (d!=x.d)
return d<x.d;
for (int i=d;i>=1;i--)
if (v[i]!=x.v[i])
return v[i]<x.v[i];
return 0;
}
bool bigger(BigInt &x){
if (d!=x.d)
return d>x.d;
for (int i=d;i>=1;i--)
if (v[i]!=x.v[i])
return v[i]>x.v[i];
return 0;
}
bool operator <(BigInt &x){//cmp abs
if (f!=x.f)
return f;
if (f&&x.f)
return (*this).bigger(x);
return (*this).smaller(x);
}
bool operator >(BigInt &x){
if (f!=x.f)
return x.f;
if (f&&x.f)
return (*this).smaller(x);
return (*this).bigger(x);
}
bool smqu(BigInt &x){
return !(*this).bigger(x);
}
bool bgqu(BigInt &x){
return !(*this).smaller(x);
}
bool operator <=(BigInt &x){
return !(*this>x);
}
bool operator >=(BigInt &x){
return !(*this<x);
}
BigInt operator +(BigInt x){//加法运算
BigInt Ans=*this;
if (f!=x.f){
Ans.f=x.f=0;
if (f)
return x-Ans;
else
return Ans-x;
}
memset(Ans.v,0,sizeof Ans.v);
Ans.f=f,Ans.d=max(d,x.d);
for (int i=1;i<=Ans.d;i++)
Ans.v[i]=v[i]+x.v[i];
for (int i=1;i<=Ans.d;i++)
Ans.v[i+1]+=Ans.v[i]/mod,Ans.v[i]%=mod;
if (Ans.v[Ans.d+1])
Ans.d++;
if (Ans.d==0)
Ans.f=0;
return Ans;
}
BigInt operator +(const LL x){
BigInt X(x);
return X+(*this);
}
BigInt operator -(BigInt y){//减法运算
BigInt Ans=*this;
if (f!=y.f){
y.f=Ans.f,Ans=Ans+y;
return Ans;
}
if (Ans.equ(y)){
Ans=0;
return Ans;
}
if (Ans.smaller(y)){
Ans=y-Ans,Ans.f=!f;
return Ans;
}
for (int i=1;i<=max(Ans.d,y.d);i++)
if (Ans.v[i]-y.v[i]<0)
Ans.v[i]+=mod-y.v[i],Ans.v[i+1]--;
else
Ans.v[i]-=y.v[i];
while (Ans.d>0&&Ans.v[Ans.d]==0)
Ans.d--;
if (Ans.d==0)
Ans.f=0;
return Ans;
}
BigInt operator -(const LL x){
BigInt Ans(x);
return (*this)-Ans;
}
BigInt operator *(const BigInt &y){//乘法运算
BigInt x=*this,Ans(0);
Ans=0,Ans.f=f^y.f;
for (int i=1;i<=x.d;i++)
for (int j=1;j<=y.d;j++){
LL now=Ans.v[i+j-1]+x.v[i]*y.v[j];
Ans.v[i+j-1]=now%mod;
Ans.v[i+1]+=now/mod;
}
Ans.d=x.d+y.d-1;
for (int i=1;i<=Ans.d;i++)
Ans.v[i+1]+=Ans.v[i]/mod,Ans.v[i]%=mod;
if (Ans.v[Ans.d+1])
Ans.d++;
if (Ans.d==0)
Ans.f=0;
return Ans;
}
BigInt operator *(LL y){
BigInt Ans=*this;
if (y<0)
Ans.f^=1;
y=abs(y);
for (int i=1;i<=d;i++)
Ans.v[i]*=y;
for (int i=1;i<=d||Ans.v[i]>0;i++)
Ans.v[i+1]+=Ans.v[i]/mod,Ans.v[i]%=mod,Ans.d=max(d,i);
if (Ans.d==0)
Ans.f=0;
return Ans;
}
BigInt operator /(BigInt y){//除法运算
BigInt Ans(0),x=*this,minus;
bool Ansf=f^y.f;
x.f=y.f=0,minus=y;
while ((minus*10).smqu(x))
minus=minus*10;
while (minus.bgqu(y)){
Ans=Ans*10;
while (minus.smqu(x))
x=x-minus,Ans=Ans+1;
minus=minus/10;
}
Ans.f=Ansf;
if (Ans.d==0)
Ans.f=0;
return Ans;
}
BigInt operator /(LL x){
BigInt Ans(0);
LL prev=0;
Ans.f=f^(x<0),Ans.d=0,x=abs(x);
for (int i=d;i>0;i--){
prev=prev*mod+v[i];
if (prev>=x)
Ans.v[i]=prev/x,prev%=x,Ans.d=max(Ans.d,i);
}
if (Ans.d==0)
Ans.f=0;
return Ans;
}
BigInt operator %(BigInt y){//取模运算
BigInt x=*this,minus;
bool xfz=f^y.f;
x.f=y.f=0,minus=y;
if (x<y){
x.f=xfz;
return x;
}
while ((minus*10).smqu(x))
minus=minus*10;
while (minus.bgqu(y)){
while (minus.smqu(x))
x=x-minus;
minus=minus/10;
}
x.f=xfz;
if (x.d==0)
x.f=0;
return x;
}
LL operator %(LL x){
LL prev=0;
bool flag=f^(x<0);
x=abs(x);
for (int i=d;i>0;i--)
prev=prev*mod+v[i],prev%=x;
if (flag)
prev=-prev;
return prev;
}
BigInt operator ^(int x){
BigInt Ans;
Ans=1;
if (x==0)
return Ans;
Ans=*this^(x/2);
Ans=Ans*Ans;
if (x&1)
Ans=Ans**this;
return Ans;
}
}zero(0),one(1);
BigInt GcdY(BigInt x,BigInt y){
BigInt z;
while (y!=zero){
z=y;
y=x%y;
x=z;
}
return x;
}
BigInt Gcd(BigInt x,BigInt y){
x.f=y.f=0;
if (x==zero)
return y;
if (y==zero)
return x;
return GcdY(x,y);
}
BigInt LcmY(BigInt x,BigInt y){
return x/GcdY(x,y)*y;
}
BigInt Lcm(BigInt x,BigInt y){
x.f=y.f=0;
if (x==zero)
return y;
if (y==zero)
return x;
return LcmY(x,y);
}
BigInt abs(BigInt x){
x.f=0;
return x;
}
void read(char ch,BigInt &x){
if (ch=='c'){
char str[MaxLen];
scanf("%s",str),x=str;
}
if (ch=='i'){
int y;
scanf("%d",&y),x=y;
}
if (ch=='L'){
LL y;
scanf("%lld",&y),x=y;
}
}
void readint(BigInt &x,int &ret){
scanf("%d",&ret),x=ret;
}
void readLL(BigInt &x,LL &ret){
scanf("%lld",&ret),x=ret;
}
// var board
const int N=100+5;
int n;
BigInt a[N][N];
struct BigDouble{
BigInt a,b;
void Print(){
(*this).Smaller();
if (a==zero){
printf("0");
return;
}
if (b==one)
a.Print();
else
a.Print('/'),b.Print();
}
void Print(char ch){
(*this).Smaller();
if (a==zero){
printf("0%c",ch);
return;
}
if (b==one)
a.Print(ch);
else
a.Print('/'),b.Print(ch);
}
void Smaller(){
if (a==zero||b==zero)
return;
// a.Print('\n');b.Print('\n');
BigInt gcd=Gcd(a,b);
// puts("Small achieve");
a=a/gcd,b=b/gcd;
// puts("div adchive");
if (b.f)
a.f^=1,b.f^=1;
}
void operator = (BigInt x){
a=x,b=one;
}
BigDouble operator * (BigDouble x){
BigDouble ans;
ans.a=a*x.a,ans.b=b*x.b;
ans.Smaller();
return ans;
}
BigDouble operator * (BigInt x){
BigDouble ans;
ans.a=x*a,ans.b=b;
ans.Smaller();
return ans;
}
BigDouble operator - (BigDouble x){
BigDouble ans;
BigInt lcm=Lcm(b,x.b),tt=lcm/b,tx=lcm/x.b;
// BigInt lcm=one,tt=one,tx=one;
ans.b=lcm,ans.a=a*tt-x.a*tx;
ans.Smaller();
return ans;
}
BigDouble operator / (BigInt x){
BigDouble ans;
// b.Print('\n');x.Print('\n');
ans.a=a,ans.b=b*x;
// puts("still alive");
ans.Smaller();
return ans;
}
BigDouble operator / (BigDouble x){
BigDouble ans;
ans.a=a*x.b,ans.b=b*x.a;
ans.Smaller();
return ans;
}
}x[N];
// var board
void Debug(){
for (int i=0;i<n;i++){
for (int j=0;j<=n;j++)
a[i][j].Print(' ');
puts("");
}
}
bool Gauss(){
int k,c;
for (k=c=0;k<n&&c<n;k++,c++){
int Mk;
for (Mk=k;Mk<n&&a[Mk][c]==zero;Mk++);
if (Mk>=n)
return 0;
if (Mk!=k)
for (int i=c;i<=n;i++)
swap(a[k][i],a[Mk][i]);
for (int i=k+1;i<n;i++)
if (a[i][c]!=zero){
BigInt lcm=Lcm(a[i][c],a[k][c]);
BigInt ta=lcm/a[i][c],tb=lcm/a[k][c];
for (int j=c;j<=n;j++)
a[i][j]=a[i][j]*ta-a[k][j]*tb;
}
// Debug();
}
for (int i=n-1;i>=0;i--){
BigDouble tmp;
tmp=a[i][n];
for (int j=i+1;j<n;j++){
// x[j].Print('\n');
// a[i][j].Print('\n');
// tmp.Print('\n');
tmp=tmp-x[j]*a[i][j];
}
// x[i].Print('\n'),tmp.Print('\n'),a[i][i].Print('\n');
x[i]=tmp/a[i][i];
}
return 1;
}
int main(){
while (~scanf("%d",&n)){
for (int i=0;i<n;i++)
for (int j=0;j<=n;j++)
read('c',a[i][j]);
for (int i=0;i<n;i++){
BigInt GCD=zero;
for (int j=0;j<=n;j++)
if (a[i][j]!=zero){
if (GCD==zero)
GCD=a[i][j];
else
GCD=Gcd(GCD,a[i][j]);
}
if (GCD!=zero)
for (int j=0;j<=n;j++)
a[i][j]=a[i][j]/GCD;
}
// Debug();
// Gauss();continue;
if (Gauss())
for (int i=0;i<n;i++)
x[i].Print('\n');
else
puts("No solution.");
puts("");
}
return 0;
}