复习了一下高斯消元解图上期望概率,笔记的话,就直接去看SengXian的blog吧.
BZOJ 1444 - [Jsoi2009]有趣的游戏
见https://blog.sengxian.com/solutions/bzoj-1444
#include <cstdio> #include <cstring> #include <algorithm> const int N=11; char s[N*2]; int n,m,l,cnt,trans[N*N][N],id[N*N],fail[N*N],pos[N],queue[N*N],front,back; double a[N*N][N*N],temp[N*N][N*N],pro[N]; inline void insert(int x){ int i,p=0; for(i=1;i<=l;++i){ if(!trans[p][s[i]-'A'])trans[p][s[i]-'A']=++cnt; p=trans[p][s[i]-'A']; } id[p]=x,pos[x]=p; } inline void Build(){ front=back=0; queue[back++]=0; int x,i; while(front!=back){ x=queue[front++]; for(i=0;i<m;++i) if(trans[x][i]){ queue[back++]=trans[x][i]; fail[trans[x][i]]=x?trans[fail[x]][i]:0; }else trans[x][i]=x?trans[fail[x]][i]:0; } } inline void PF(){ register int i,j,k; for(i=0;i<=cnt;++i) for(j=0;j<=cnt;++j) temp[i][j]=0; for(i=0;i<=cnt;++i) for(j=0;j<=cnt;++j) for(k=0;k<=cnt;++k) temp[i][j]+=a[i][k]*a[k][j]; for(i=0;i<=cnt;++i) for(j=0;j<=cnt;++j) a[i][j]=temp[i][j]; } int main(){ //freopen("rio.txt","r",stdin); scanf("%d%d%d",&n,&l,&m); int i,j,x,y; for(i=0;i<m;++i){ scanf("%d%d",&x,&y); pro[i]=(double)x/y; } for(i=1;i<=n;++i){ scanf("%s",s+1); insert(i); } Build(); for(i=0;i<=cnt;++i) if(!id[i]) for(j=0;j<m;++j) a[trans[i][j]][i]+=pro[j]; else a[i][i]=1; int T=50; while(T--)PF(); for(i=1;i<=n;++i) printf("%.2f ",a[pos[i]][0]); return 0; }
#include <cmath> #include <cstdio> #include <cstring> #include <algorithm> const int N=11; char s[N*2]; int n,m,l,cnt,trans[N*N][N],id[N*N],fail[N*N],pos[N],queue[N*N],front,back; double a[N*N][N*N],pro[N],b[N*N]; inline void insert(int x){ int i,p=0; for(i=1;i<=l;++i){ if(!trans[p][s[i]-'A'])trans[p][s[i]-'A']=++cnt; p=trans[p][s[i]-'A']; } id[p]=x,pos[x]=p; } inline void Build(){ front=back=0; queue[back++]=0; int x,i; while(front!=back){ x=queue[front++]; for(i=0;i<m;++i) if(trans[x][i]){ queue[back++]=trans[x][i]; fail[trans[x][i]]=x?trans[fail[x]][i]:0; }else trans[x][i]=x?trans[fail[x]][i]:0; } } inline void Gauss(){ int i,j,k,index; double mul; for(i=0;i<=cnt;++i){ index=i; for(j=i+1;j<=cnt;++j) if(std::fabs(a[j][i])>std::fabs(a[index][i])) index=j; if(std::fabs(a[index][i])==0)continue; if(index!=i) for(j=i;j<=cnt+1;++j) std::swap(a[i][j],a[index][j]); for(j=i+1;j<=cnt;++j){ mul=a[j][i]/a[i][i]; for(k=i;k<=cnt+1;++k) a[j][k]-=mul*a[i][k]; } } for(i=cnt;i>=0;--i){ for(j=i+1;j<=cnt;++j) a[i][cnt+1]-=a[i][j]*b[j]; b[i]=a[i][cnt+1]/a[i][i]; } } int main(){ //freopen("rio.txt","r",stdin); scanf("%d%d%d",&n,&l,&m); int i,j,x,y; for(i=0;i<m;++i){ scanf("%d%d",&x,&y); pro[i]=y==0?0:(double)x/y; } for(i=1;i<=n;++i){ scanf("%s",s+1); insert(i); } Build(); for(i=0;i<=cnt;++i) if(!id[i]) for(j=0;j<m;++j) a[trans[i][j]][i]+=pro[j]; for(i=0;i<=cnt;++i) a[i][i]-=1; a[0][cnt+1]=-1; Gauss(); for(i=1;i<=n;++i) printf("%.2f ",std::fabs(b[pos[i]])); return 0; }
BZOJ 3143 - [Hnoi2013]游走
见https://blog.sengxian.com/solutions/bzoj-3143
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define MAXN 510 using namespace std; typedef double D; struct T { int to,next,w; }c[MAXN*MAXN]; int head[MAXN],tot; int n,m; D a[MAXN][MAXN],f[MAXN],g[MAXN*MAXN],d=1.00; inline void add(int x,int y,int z) { c[++tot].to=y; c[tot].next=head[x]; c[tot].w=z; head[x]=tot; c[++tot].to=x; c[tot].next=head[y]; c[tot].w=z; head[y]=tot; } int in[MAXN]; inline D abs(D x) { return x<0?0-x:x; } inline void swap(D &x,D &y) { D temp=x; x=y; y=temp; } inline void gas() { for(int i=1,k=1;i<=n;i++,k++) { D h=abs(a[i][k]); int t=i; for(int j=i+1;j<=n;j++) if(abs(a[j][k]>h)) { h=abs(a[j][k]); t=j; } if(t!=i) { for(int j=k;j<=n+1;j++) swap(a[i][j],a[t][j]); } for(int j=i+1;j<=n;j++) { D to=a[j][k]/a[i][k]; for(int l=k;l<=n+1;l++) a[j][l]-=a[i][l]*to; } } for(int i=n;i>0;i--) { for(int j=i+1;j<=n;j++) a[i][n+1]-=a[i][j]*f[j]; f[i]=a[i][n+1]/a[i][i]; } } inline void work() { for(int i=1;i<n;i++) for(int j=head[i];j;j=c[j].next) g[c[j].w]+=f[i]/in[i]; sort(g+1,g+m+1); D ans=0; for(int i=1;i<=m;i++) ans+=(D)(m-i+1)*g[i]; printf("%.3lf",ans); } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { int x,y; scanf("%d%d",&x,&y); add(x,y,i); in[x]++; in[y]++; } in[n]=1; for(int i=1;i<=n;i++) { a[i][i]=-1; for(int j=head[i];j;j=c[j].next) if(c[j].to!=n) a[i][c[j].to]=(D)(d/in[c[j].to]); a[i][n+1]=0.00; } a[1][n+1]=-1.00; gas(); work(); return 0; }
BZOJ 3640 - JC的小苹果
见https://blog.sengxian.com/solutions/bzoj-3640
#include <cmath> #include <cstdio> #include <cstring> #include <algorithm> const int N=155; const int M=5010; const int H=10010; int n,m,hp,co[N]; double a[N][N],b[N],f[H][N]; struct B{ double x[N]; inline friend B operator -(B w,B q){ int i; for(i=1;i<=n;++i) w.x[i]-=q.x[i]; return w; } inline friend B operator *(B w,double q){ int i; for(i=1;i<=n;++i) w.x[i]*=q; return w; } inline double get(){ double ret=0; int i; for(i=1;i<=n;++i) ret+=x[i]*b[i]; return ret; } }bi[N]; struct V{ int to,next; }c[M<<1]; int head[N],t; int degree[N]; inline void add(int x,int y){ c[++t].to=y,c[t].next=head[x],head[x]=t; } inline void Gauss(){ int i,j,k,idx; double mul; for(i=1;i<=n;++i){ idx=i; for(j=i+1;j<=n;++j) if(std::fabs(a[j][i])>std::fabs(a[idx][i])) idx=j; if(idx!=i){ for(j=i;j<=n;++j) std::swap(a[i][j],a[idx][j]); std::swap(bi[i],bi[idx]); } for(j=1;j<=n;++j){ if(i==j)continue; mul=a[j][i]/a[i][i]; for(k=i;k<=n;++k) a[j][k]-=a[i][k]*mul; bi[j]=bi[j]-bi[i]*mul; } } } inline void Gauss(double *e){ int i,j; double sum; for(i=n;i>0;--i) e[i]=bi[i].get()/a[i][i]; } inline void Init(){ scanf("%d%d%d",&n,&m,&hp); int i,j,x,y; for(i=1;i<=n;++i) scanf("%d",&co[i]); for(i=1;i<=m;++i){ scanf("%d%d",&x,&y); if(x==y){ add(x,y); ++degree[x]; continue; } add(x,y),add(y,x); ++degree[x],++degree[y]; } for(i=1;i<=n;++i){ bi[i].x[i]=1; if(co[i])a[i][i]=1; else{ a[i][i]=-1; for(j=head[i];j;j=c[j].next) if(c[j].to!=n) a[i][c[j].to]+=1./degree[c[j].to]; } } Gauss(); } inline void Work(){ int i,j,k; for(i=hp;i>0;--i){ for(j=1;j<=n;++j){ b[j]=0; if(j==1&&i==hp) b[j]=-1; else if(!co[j]) b[j]=0; else if(i+co[j]<=hp) for(k=head[j];k;k=c[k].next) if(c[k].to!=n) b[j]+=f[i+co[j]][c[k].to]/degree[c[k].to]; } Gauss(f[i]); } } inline void Print(){ double ans=0; int i; for(i=1;i<=hp;++i) ans+=f[i][n]; printf("%.8lf ",ans); } int main(){ //freopen("rio.txt","r",stdin); Init(); Work(); Print(); return 0; }