标签:har 模板 comm ogre 网上 高精度加法 lld day 想法
原文链接https://www.cnblogs.com/zhouzhendong/p/HDU2449.html
高精度高斯消元。
输入 $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