码迷,mamicode.com
首页 > 编程语言 > 详细

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

时间:2018-07-08 23:11:04      阅读:222      评论:0      收藏:0      [点我收藏+]

标签:har   模板   comm   ogre   网上   高精度加法   lld   day   想法   

原文链接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$ 。

  ……

  技术分享图片

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

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

 

  注:今天之前的上一次提交是在 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;
}

  

 

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

标签:har   模板   comm   ogre   网上   高精度加法   lld   day   想法   

原文地址:https://www.cnblogs.com/zhouzhendong/p/HDU2449.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!