一、整数高斯消元:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#define ll long long
using namespace std;
const int maxn=20;
int gcd(int a,int b)
{
if(b==0) return a;
else return gcd(b,a%b);
}
int lcm(int a,int b)
{
return a/gcd(a,b)*b;
}
int a[maxn][maxn];
int x[maxn];
int free_x[maxn];
int Gauss(int equ,int var)
{
int k,col,max_r,ta,tb;
int LCM,temp,free_x_num,free_index;
for(int i=0;i<=var;i++)
x[i]=0,free_x[i]=1;
for(k=0,col=0;k<equ&&col<var;k++,col++)
{
max_r=k;
for(int i=k+1;i<equ;i++)
{
if(abs(a[i][col])>abs(a[max_r][col])) max_r=i;
}
if(max_r!=k)
{
for(int j=k;j<var+1;j++) swap(a[k][j],a[max_r][j]);
//for(int j=col;j<var+1;j++) swap(a[k][j],a[max_r][j]);
}
if(a[k][col]==0)
{
k--;
continue;
}
for(int 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(int j=col;j<var+1;j++)
{
a[i][j]=a[i][j]*ta-a[k][j]*tb;
}
}
}
}
for(int i=k;i<equ;i++)
{
if(a[i][col]!=0) return -1;
}
if(k<var)
{
for(int i=k-1;i>=0;i--)
{
free_x_num=0;
for(int j=0;j<var;j++)
{
if(a[i][j]&&free_x[j]) free_x_num++,free_index=j;
}
if(free_x_num>1) continue;
temp=a[i][var];
for(int j=0;j<var;j++)
{
if(a[i][j]&&j!=free_index) temp-=a[i][j]*x[j];
}
x[free_index]=temp/a[i][free_index];
free_x[free_index]=0;
}
return var-k;
}
for(int i=var-1;i>=0;i--)
{
temp=a[i][var];
for(int j=i+1;j<var;j++)
{
if(a[i][j]) temp-=a[i][j]*x[j];
}
if(temp%a[i][i]!=0) return -2;
x[i]=temp/a[i][i];
}
return 0;
}
int main(void)
{
int equ,var;
while(scanf("%d%d",&equ,&var)!=EOF)
{
for(int i=0;i<equ;i++)
{
for(int j=0;j<=var;j++)
scanf("%d",&a[i][j]);
}
int k=Gauss(equ,var);
if(k==-1) cout<<"no answer!\n";
if(k==-2) cout<<"you xiao shu jie\n";
if(k==0)
{
cout<<"This: ";
for(int i=0;i<var;i++)
printf("%d ",x[i]);
putchar('\n');
}
if(k>0)
{
printf("free: %d\n",k);
for(int i=0;i<var;i++)
{
printf("%d ",x[i]);
putchar('\n');
}
}
}
return 0;
}
二、浮点数高斯消元
int Gauss(int m,int n)
{
int k,col;
for(k=0,col=0;k<m&&col<n;k++,col++)
{
int r=k;
for(int i=k+1;i<m;i++)
if(fabs(a[i][col])>fabs(a[r][col])) r=i;
if(fabs(a[r][col])<eps)
{
k--;
continue;
}
if(r!=k)
{
for(int i=col;i<=n;i++)
swap(a[r][i],a[k][i]);
}
for(int i=k+1;i<m;i++)
{
if(fabs(a[i][col])>eps)
{
double t=a[i][col]/a[k][col];
for(int j=col;j<=n;j++)
a[i][j]-=a[k][j]*t;
a[i][col]=0;
}
}
}
for(int i=k;i<m;i++)
if(fabs(a[i][n])>eps) return -1;
if(k<n) return n-k;
for(int i=n-1;i>=0;i--)
{
double temp=a[i][n];
for(int j=i+1;j<n;j++)
temp-=x[j]*a[i][j];
x[i]=temp/a[i][i];
}
return 0;
}
球形空间产生器sphere HYSBZ - 1013
有一个球形空间产生器能够在n维空间中产生一个坚硬的球体。现在,你被困在了这个n维球体中,你只知道球
面上n+1个点的坐标,你需要以最快的速度确定这个n维球体的球心坐标,以便于摧毁这个球形空间产生器。
Input
第一行是一个整数n(1<=N=10)。接下来的n+1行,每行有n个实数,表示球面上一点的n维坐标。每一个实数精确到小数点
后6位,且其绝对值都不超过20000。
Output
有且只有一行,依次给出球心的n维坐标(n个实数),两个实数之间用一个空格隔开。每个实数精确到小数点
后3位。数据保证有解。你的答案必须和标准输出一模一样才能够得分。
Sample Input
2
0.0 0.0
-1.0 1.0
1.0 0.0
Sample Output
0.500 1.500
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn = 20;
double a[maxn][maxn],b[maxn]={0.0},c[maxn][maxn];
int n;
int main(void)
{
cin>>n;
for(int i=1;i<=n+1;i++)
{
for(int j=1;j<=n;j++)
{
scanf("%lf",&a[i][j]);
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
c[i][j]=2*(a[i][j]-a[i+1][j]);
b[i]+=a[i][j]*a[i][j]-a[i+1][j]*a[i+1][j];
}
}
for(int i=1;i<=n;i++)
{
for(int j=i;j<=n;j++)
{
if(abs(c[j][i])>1e-8)
{
for(int k=1;k<=n;k++) swap(c[i][k],c[j][k]);
swap(b[i],b[j]);
}
}
for(int j=1;j<=n;j++)
{
if(i==j) continue;
double rate=c[j][i]/c[i][i];
for(int k=i;k<=n;k++) c[j][k]-=c[i][k]*rate;
b[j]-=b[i]*rate;
}
}
for(int i=1;i<n;i++) printf("%.3f ",b[i]/c[i][i]);
printf("%.3f\n",b[n]/c[n][n]);
return 0;
}
三、高斯消元解异或方程组
int Guass()
{
int max_r,col,k;
free_num=0;
for(k=0,col=0;k<equ&&col<var;k++,col++)
{
max_r=k;
for(int i=k+1;i<equ;i++)
{
if(abs(a[i][col])>abs(a[max_r][col])) max_r=i;
}
if(a[max_r][col]==0)
{
k--;
free_x[free_num++]=col;
continue;
}
if(max_r!=k)
{
for(int j=col;j<var+1;j++)
swap(a[k][j],a[max_r][j]);
}
for(int i=k+1;i<equ;i++)
{
if(a[i][col]!=0)
{
for(int j=col;j<var+1;j++)
a[i][j]^=a[k][j];
}
}
}
for(int i=k;i<equ;i++)
if(a[i][col]!=0) return -1;
if(k<var) return var-k;
for(int i=var-1;i>=0;i--)
{
x[i]=a[i][col];
for(int j=i+1;j<var;j++)
{
x[i]^=(a[i][j]&&x[j]);
}
}
return 0;
}
int mj(void)
{
int t=Gauss();
if(t==-1)
{
return -1;
}
else if(t==0)
{
int ans=0;
for(int i=0;i<n*n;i++)
{
ans+=x[i];
}
return ans;
}
else
{
int ans=0x3f3f3f3f;
int tot=(1<<t);
for(int i=0;i<tot;i++)
{
int cnt=0;
for(int j=0;j<t;j++)
{
if(i&(1<<j))
{
x[free_x[j]]=1;
cnt++;
}
else x[free_x[j]]=0;
}
for(int j=var-t-1;j>=0;j--)
{
int index;
for(index=j;index<var;index++)
{
if(a[j][index]) break;
}
x[idnex]=a[j][var];
for(int l=index+1;l<var;l++)
{
if(a[j][l])
x[idnex]^=x[l];
}
cnt+=x[index];
}
ans=min(ans,cnt);
}
return ans;
}
}
POJ1681
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int maxn=300;
int equ,var;
int a[maxn][maxn];
int x[maxn];
int free_x[maxn];
int free_num;
int n;
//考虑有 n*n 个多项式,每一个多项式涉及到上下左右以及自身的五个变量
//对于某个格子,对其涂两次相当于没涂,涂三次相当于涂一次
//所以只有涂0次和1次之分
void init()
{
memset(a,0,sizeof(a));
memset(x,0,sizeof(x));
equ=n*n;
var=n*n;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
{
int t=i*n+j;
a[t][t]=1;
if(i>0) a[(i-1)*n+j][t]=1;
if(i<n-1) a[(i+1)*n+j][t]=1;
if(j>0) a[i*n+j-1][t]=1;
if(j<n-1) a[i*n+j+1][t]=1;
}
}
int Guass()
{
int max_r,col,k;
free_num=0;
for(k=0,col=0;k<equ&&col<var;k++,col++)
{
max_r=k;
for(int i=k+1;i<equ;i++)
{
if(abs(a[i][col])>abs(a[max_r][col])) max_r=i;
}
if(a[max_r][col]==0)
{
k--;
free_x[free_num++]=col;
continue;
}
if(max_r!=k)
{
for(int j=col;j<var+1;j++)
swap(a[k][j],a[max_r][j]);
}
for(int i=k+1;i<equ;i++)
{
if(a[i][col]!=0)
{
for(int j=col;j<var+1;j++)
a[i][j]^=a[k][j];
}
}
}
for(int i=k;i<equ;i++)
if(a[i][col]!=0) return -1;
if(k<var) return var-k;
for(int i=var-1;i>=0;i--)
{
x[i]=a[i][col];
for(int j=i+1;j<var;j++)
{
x[i]^=(a[i][j]&&x[j]);
}
}
return 0;
}
int mj(void)
{
int t=Guass();
if(t==-1)
{
return -1;
}
else if(t==0)
{
int ans=0;
for(int i=0;i<n*n;i++)
{
ans+=x[i];
}
return ans;
}
else
{
int ans=0x3f3f3f3f;
int tot=(1<<t);
for(int i=0;i<tot;i++)
{
int cnt=0;
for(int j=0;j<t;j++)
{
if(i&(1<<j))
{
x[free_x[j]]=1;
cnt++;
}
else x[free_x[j]]=0;
}
for(int j=var-t-1;j>=0;j--)
{
int index;
for(index=j;index<var;index++)
{
if(a[j][index]) break;
}
x[index]=a[j][var];
for(int l=index+1;l<var;l++)
{
if(a[j][l])
x[index]^=x[l];
}
cnt+=x[index];
}
ans=min(ans,cnt);
}
return ans;
}
}
char str[maxn][maxn];
int main(void)
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
init();
for(int i=0;i<n;i++)
{
scanf("%s",str[i]);
for(int j=0;j<n;j++)
{
if(str[i][j]=='y')
a[i*n+j][n*n]=0;
else a[i*n+j][n*n]=1;
}
}
int k=mj();
if(k==-1) printf("inf\n");
else printf("%d\n",k);
}
return 0;
}
四、解同余方程组:
几乎与解整数方程组一样:
POJ2947
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<map>
#define ll long long
using namespace std;
const int maxn=400;
const int mod=7;
int equ,var;
int a[maxn][maxn];
int x[maxn];
int free_x[maxn];
int free_num;
int n;
map<string,int>mp;
int gcd(int a,int b)
{
if(b==0) return a;
else return gcd(b,a%b);
}
int lcm(int a,int b)
{
return a/gcd(a,b)*b;
}
int inv(int a)
{
if(a==1) return 1;
return (mod-mod/a)%mod*inv(mod%a);
}
void init(void)
{
mp["MON"]=1;
mp["TUE"]=2;
mp["WED"]=3;
mp["THU"]=4;
mp["FRI"]=5;
mp["SAT"]=6;
mp["SUN"]=7;
}
int Guass(int equ,int var)
{
int max_r,k,col;
for(k=0,col=0;k<equ&&col<var;k++,col++)
{
max_r=k;
for(int i=k+1;i<equ;i++)
if(abs(a[i][col])>abs(a[max_r][col])) max_r=i;
if(a[max_r][col]==0)
{
k--;
continue;
}
if(max_r!=k)
for(int i=col;i<=var;i++)
swap(a[k][i],a[max_r][i]);
for(int i=k+1;i<equ;i++)
{
if(a[i][col]!=0)
{
int LCM=lcm(a[i][col],a[k][col]);
int ta=LCM/abs(a[i][col]);
int tb=LCM/abs(a[k][col]);
if(a[i][col]*a[k][col]<0) tb=-tb;
for(int j=col;j<=var;j++)
{
a[i][j]=((a[i][j]*ta-a[k][j]*tb)%mod+mod)%mod;
}
}
}
}
for(int i=k;i<equ;i++)
{
if(a[i][col]!=0) return -1;
}
if(k<var) return var-k;
for(int i=var-1;i>=0;i--)
{
int temp=a[i][var];
for(int j=i+1;j<var;j++)
{
if(a[i][j]!=0)
{
temp-=a[i][j]*x[j];
temp=(temp%mod+mod)%mod;
}
}
x[i]=(temp*inv(a[i][i]))%mod;
}
return 0;
}
int main(void)
{
int n,m;
init();
while(scanf("%d%d",&n,&m),n||m)
{
memset(a,0,sizeof(a));
char str1[10],str2[10];
int k;
for(int i=0;i<m;i++)
{
scanf("%d%s%s",&k,str1,str2);
a[i][n]=((mp[str2]-mp[str1]+1)%mod+mod)%mod;
int t;
for(int j=1;j<=k;j++)
{
scanf("%d",&t);
a[i][--t]++;
a[i][t]%=mod;
}
}
int ans=Guass(m,n);
if(ans==0)
{
for(int i=0;i<n;i++)
if(x[i]<=2) x[i]+=7;
for(int i=0;i<n-1;i++)
{
printf("%d ",x[i]);
}
printf("%d\n",x[n-1]);
}
else if(ans==-1)
{
printf("Inconsistent data.\n");
}
else printf("Multiple solutions.\n");
}
return 0;
}