BZOJ1875: [SDOI2009]HH去散步 图上边矩乘
Posted TS_Hugh
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ1875: [SDOI2009]HH去散步 图上边矩乘相关的知识,希望对你有一定的参考价值。
这道题十分的坑……
我作为一只连矩乘都不太会的渣渣看到这道题就只能神搜了…..
首先说一下普通的矩乘求方案,就是高出邻接矩阵然后一顿快速幂…..
矩乘一般就是一些秘制递推…..
再说一下这道题,我们可以看出这小骚题有个条件就是说,不能立刻回头,这就不能用以往的了,以往的前后顺序无关,在矩阵里放的是:f[i][j]就是说第i个状态可以由第j个状态转移而来,那么我们可以看出若这个边为无向边,那么对于->*来说这个->东西可以无脑转移到*,因为*是->的合法状态也是唯几合法状态…..
最后的答案把->到B的加起来就好了…….
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 #include<cstdio> #include<cstring> #define N 25 #define M 65 #define P 45989 using namespace std; inline int read() { int sum=0; char ch=getchar(); while(ch<‘0‘||ch>‘9‘)ch=getchar(); while(ch>=‘0‘&&ch<=‘9‘) { sum=(sum<<1)+(sum<<3)+ch-‘0‘; ch=getchar(); } return sum; } int a[M<<1][M<<1],b[M<<1]; int n,m,T,A,B; struct Tr { int to,next,id; }c[M<<1]; int head[N],t; inline void add(int x,int y) { c[++t].to=y; c[t].next=head[x]; c[t].id=t; head[x]=t; } bool En[M<<1]; inline void look() { printf("LET US SEE B\n"); for(int i=1;i<=(m<<1);i++) printf(" %d ",b[i]); printf("\n"); } inline void Init() { n=read(),m=read(),T=read(),A=read()+1,B=read()+1; for(int i=1;i<=m;i++) { int x=read()+1,y=read()+1; add(x,y),add(y,x); } for(int x=1;x<=n;x++) { for(int i=head[x];i;i=c[i].next) { int y=c[i].to; if(y==B)En[c[i].id]=1; int caocaocao=0; for(int j=head[y];j;j=c[j].next) { if(c[j].to==x) caocaocao++; if(c[j].to!=x||(c[j].to==x&&caocaocao!=1)) a[c[j].id][c[i].id]=1; } } } for(int i=head[A];i;i=c[i].next) b[c[i].id]=1; } int temp[M<<1][M<<1],d[M<<1]; inline void up() { memset(d,0,sizeof(d)); for(int i=1;i<=(m<<1);i++) for(int j=1;j<=(m<<1);j++) d[i]+=a[i][j]*b[j]%P; for(int i=1;i<=(m<<1);i++) b[i]=d[i]%P; } inline void multi() { memset(temp,0,sizeof(temp)); for(int i=1;i<=(m<<1);i++) for(int j=1;j<=(m<<1);j++) for(int k=1;k<=(m<<1);k++) temp[i][j]+=a[i][k]*a[k][j]%P; for(int i=1;i<=(m<<1);i++) for(int j=1;j<=(m<<1);j++) a[i][j]=temp[i][j]%P; } inline void work() { T=T-1; while(T) { //look(); if(T&1)up(); T>>=1; multi(); } int ans=0; for(int i=1;i<=(m<<1);i++) if(En[i]) ans+=b[i]; ans%=P; printf("%d",ans); } int main() { Init(); if(T==0) { if(A==B)printf("1"); else printf("0"); return 0; } work(); return 0; }
以上是关于BZOJ1875: [SDOI2009]HH去散步 图上边矩乘的主要内容,如果未能解决你的问题,请参考以下文章
BZOj-1875: [SDOI2009]HH去散步 (矩阵快速幂)
bzoj 1875: [SDOI2009]HH去散步 -- 矩阵乘法