【预备知识】首先你要保证你懂下面的东西,才有必要往下看。

                      1.矩阵的基本运算。

                      2.知道一些行列式的基本性质。

【算法描述】高斯消元!

【算法原理】

参见算法入门经典P155

本来是想放现代书的原理的,可惜书找不到了。懂了这张图片,大概就懂高斯消元的基本原理了。那么代码就很好写了。我给一个算法实现!选自白书模板。

【算法实现】

参见算法入门经典P156

【入门例题or毒瘤】

【UESTC 祝爷和远古法阵】

【题目链接】点击打开链接

【解题思路】dp[i]表示在i位置的期望,那么容易得到dp[i] = (dp[i+1]+dp[i+1]+dp[i+2]+dp[i+3]+dp[i+4]+dp[i+5]+dp[i+6])/6+1;那么传送门可以表示为dp[u]=dp[v],这些都是为了构造小圆的增广矩阵的。那么变形一下,可以知道6*dp[i]-dp[i-1]-dp[i-2]-dp[i-3]-dp[i-4]-dp[i-5]-dp[i-6]=6;dp[u]-dp[v]=0;

【补充】构造完矩阵就可以跑高斯小圆了。这题特别毒瘤的是卡进度啊啊 啊啊。。。还有为了提高输入效率,这里使用读入挂。

【选自UESTC算法讲堂】对高斯消元入门一下。

【AC代码】

#include <bits/stdc++.h>
using namespace std;
const int maxn = 305;
const long double eps=1e-14;
long double a[maxn][maxn];
int n,m,f[maxn],x,y;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int main(){
    n=read(),m=read();
    for(int i=1; i<=n; i++) f[i]=i;
    for(int i=1; i<=m; i++) f[read()]=read();
    //矩阵构造
    for(int i=1; i<n; i++)
    {
        a[i][i]=6;
        if(f[i]!=i) a[i][f[i]]=-6;
        else
        {
            a[i][n+1]=6;
            for(int j=1; j<=6; j++)
            {
                if(i+j<=n) a[i][i+j]=-1.0;
                else a[i][i]-=1.0;
            }
        }
    }
    //dp[n]=0;
    a[n][n]=1.0;
    a[n][n+1]=0;
    //Guass xiaoyuan
    for(int i=1; i<=n; i++)
    {
        int p=i;
        for(int j=i+1; j<=n; j++)
            if(fabs(a[j][i])>eps)
                p=j;
        if(fabs(a[p][i])>eps)
        {
            for(int j=i; j<=n+1; j++) swap(a[i][j],a[p][j]);
            for(int j=i+1; j<=n; j++)
            {
                if(fabs(a[j][i])>eps)
                {
                    long double k=a[j][i]/a[i][i];
                    for(int t=i; t<=n+1; t++) a[j][t]-=a[i][t]*k;
                }
            }
        }
    }
    //回带
    for(int i=n; i>=1; i--)
    {
        for(int j=i+1; j<=n; j++) if(fabs(a[i][j])>eps)
            a[i][n+1]-=a[i][j]*a[j][n+1];
        if(abs(a[i][i])<=eps&&abs(a[i][n+1])>eps)
        {
            printf("-1\n");
            return 0;
        }
        a[i][n+1]/=a[i][i];
    }
    printf("%.12Lf\n",a[1][n+1]);
    return 0;
}