【预备知识】首先你要保证你懂下面的东西,才有必要往下看。
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;
}