高斯消元的学习 + 辗转相除法

高斯消元的学习 + 辗转相除法

参考网站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\n",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\n",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("\n");
    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;
}
posted @ 2020-08-07 11:34  EchoZQN  阅读(497)  评论(0编辑  收藏  举报