高斯消元的学习 + 辗转相除法
参考网站1 https://oi-wiki.org/math/gauss/
参考网站2 https://www.cnblogs.com/xcg123/p/10679600.html
模板 https://www.cnblogs.com/zcysky/p/6946919.html
模板 题目:C - Museum
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1000;
const double eps=1e-8;
double a[maxn][maxn],del,ans[maxn];
bool gauss(int n) {
for (int i = 1; i <= n; i++) {
int k = i;
for (int j = i + 1; j <= n; j++) if (fabs(a[j][i]) > fabs(a[k][i]))k = j;
if (fabs(del = a[k][i]) < eps)return 0;
for (int j = i; j <= n + 1; j++) swap(a[i][j], a[k][j]);
for (int j = i; j <= n + 1; j++) a[i][j] /= del;
for (k = 1; k <= n; k++)
if (k != i) {
del = a[k][i];
for (int j = i; j <= n + 1; j++)a[k][j] -= a[i][j] * del;
}
}
for(int i=n;i>=1;i--) {
double sum = a[i][n+1];
for(int j=i+1; j<=n;j++) {
sum -= a[i][j]*ans[j];
}
ans[i] = sum;
}
return 1;
}
int w[maxn][maxn];
double p[maxn],dp[maxn][maxn],num[maxn];
int main(){
int n,m,sx,sy;
scanf("%d%d%d%d",&n,&m,&sx,&sy);
for(int i=1;i<=m;i++){
int u,v;
scanf("%d%d",&u,&v);
w[u][v]=1,w[v][u]=1;
num[u]++,num[v]++;
}
for(int i=1;i<=n;i++) scanf("%lf",&p[i]),w[i][i]=1;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
for(int x=1;x<=n;x++){
for(int y=1;y<=n+1;y++){
int gx = (i-1)*n+j,gy = (x-1)*n+y;
if(gy==n*n+1){
// printf("a[%d][%d]=%f i=%d j=%d
",gx,gy,a[gx][gy],i,j);
if(i==sx&&j==sy) a[gx][gy]=-1;
else a[gx][gy]=0;
continue;
}
if(x==i&&y==j){
if(x==y) a[gx][gy]=-1;
else a[gx][gy]=p[x]*p[y]-1;
}
else{
if(x!=y&&w[x][i]&&w[y][j]) {
if(x==i) a[gx][gy]=p[x]*(1-p[y])/num[y];
else if(y==j) a[gx][gy]=(1-p[x])*p[y]/num[x];
else a[gx][gy]=(1-p[x])*(1-p[y])/(num[x]*num[y]);
}
else a[gx][gy]=0;
}
// printf("a[%d][%d]=%f
",gx,gy,a[gx][gy]);
}
}
}
}
gauss(n*n);
for(int i=1;i<=n;i++){
int x = (i-1)*n+i;
printf("%.6f ",ans[x]);
}
printf("
");
return 0;
}
辗转相除法
https://www.cnblogs.com/zyb993963526/p/7360536.html
https://www.cnblogs.com/yangsongyi/p/10697176.html
ll K[maxn][maxn];
ll Gauss(int n){//求矩阵K的n-1阶顺序主子式
ll res=1;
for(int i=1;i<=n-1;i++){//枚举主对角线上第i个元素
for(int j=i+1;j<=n-1;j++){//枚举剩下的行
while(K[j][i]){//辗转相除
ll t=K[i][i]/K[j][i];
for(int k=i;k<=n-1;k++)//转为倒三角
K[i][k]=(K[i][k]-t*K[j][k]+mod)%mod;
swap(K[i],K[j]);//交换i、j两行
res=-res;//取负
}
}
res=(res*K[i][i])%mod;
}
return (res+mod)%mod;
}