高斯消元\高斯约当 模板

实数版:O(n^3)

解方程:

#include <cstdio>
#include <algorithm>
#define rep(i,l,r) for (int i=l;i<=r;++i)
const double EPS=1e-8;
int sign(const double &x){return x<-EPS?-1:x>EPS;}
const int MAX_N=105,MAX_M=1005;
double a[MAX_N][MAX_M+MAX_N];
int n,m;
void gauss(){
    rep(i,1,n){
        int p=1;
        rep(j,i,n) if (sign(a[j][i])){p=j;break;} //这里应该写成绝对值最大的精度高一些
        rep(k,1,n+m) std::swap(a[i][k],a[p][k]);
        rep(j,1,n) if (i!=j){
            double r=a[j][i]/a[i][i];
            rep(k,i,n+m) a[j][k]-=r*a[i][k];
            }
        }
    rep(i,n+1,n+m) rep(j,1,n)
        printf("%.3f%c",a[j][i]/a[j][j],j==n?'\n':' ');
}
int main(){
    scanf("%d%d",&n,&m);
    rep(i,1,n) rep(j,1,n) scanf("%lf",&a[i][j]);
    rep(i,n+1,n+m) rep(j,1,n) scanf("%lf",&a[j][i]);
    gauss();
}


整数版:

有O(N^3)   (LCM)

   O(N^3logM)  (模拟GCD)


O(N^3)

(C一份~~~)

int Gauss()  
{  
    int i,j,k;  
    int max_r;  
    int ta,tb;  
    int free_x_num;  
    int free_index;  
    int LCM,tmp;  
    int col = 0;  
    for(k=0; k<equ && col<var; k++,col++)  
    {  
        max_r = k;  
        for(i=k+1; i<equ; i++)  
            if(abs(a[i][col]) > abs(a[max_r][col])) max_r = i;  
        if(max_r != k)  
            for(j=k; j<var+1; j++)  
                swap(a[k][j],a[max_r][j]);  
        if(a[k][col] == 0)  
        {  
            k--;  
            continue;  
        }  
        for(i=k+1; i<equ; i++)  
        {  
            if(a[i][col] != 0)  
            {  
                LCM = lcm(abs(a[i][col]),abs(a[k][col]));  
                ta = LCM / abs(a[i][col]);  
                tb = LCM / abs(a[k][col]);  
                if(a[i][col] * a[k][col] < 0) tb = - tb;  
                for(j = col ; j<var+1; j++)  
                    a[i][j] = a[i][j]*ta - a[k][j]*tb;  
            }  
        }  
    }  



XOR方程组(没有压位):O(N^3)

压位:O(NlogMAX)

#include <cstdio>
#include <algorithm>
#define rep(i,l,r) for (int i=l;i<=r;++i)
#define per(i,r,l) for (int i=r;i>=l;--i)
const int MAX_N=40;
bool a[MAX_N][MAX_N];
int n,m;
void gauss(){
	rep(i,1,n){
		rep(j,i,n) if (a[j][i]>a[i][i]) rep(k,1,n+1) std::swap(a[i][k],a[j][k]);
		rep(j,1,n) if (i!=j&&a[j][i])   rep(k,i,n+1) a[j][k]^=a[i][k];
		}
}
int ans=100;
bool x[MAX_N];
void dfs(int v,int tot){  //自由元枚举
	if (tot>ans) return;
	if (v<=0){ans=tot;return;}
	if (a[v][v]){
		x[v]=a[v][n+1];
		rep(k,v+1,n) x[v]^=a[v][k]&x[k];
		dfs(v-1,tot+x[v]);
	}else{
		x[v]=1;dfs(v-1,tot+1);
		x[v]=0;dfs(v-1,tot);
		}
}
int main(){
	freopen("lights.in","r",stdin);
	freopen("lights.out","w",stdout);
	scanf("%d%d",&n,&m);
	rep(i,1,n) a[i][i]=a[i][n+1]=1;
	rep(i,1,m){
		int x,y;scanf("%d%d",&x,&y);
		a[x][y]=a[y][x]=1;
		}
	gauss();
	dfs(n,0);
	printf("%d\n",ans);
}



ORZ MATO: http://www.cppblog.com/MatoNo1/archive/2012/05/20/175404.html

AND :http://wenku.baidu.com/link?url=PsKxF1uwSUIoTx9zuOpTQbSPuiQrTtDSx_TnGXI6r_nw1Evg37lqXOJL3CODAokkV9JVhw4qqXMGhyItwihn-cjan1jKth7-PQoB0s9nN1K

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值