1. 程式人生 > >bzoj1875 [SDOI2009]HH去散步——矩陣快速冪

bzoj1875 [SDOI2009]HH去散步——矩陣快速冪

n) code ios TP pac lan sdoi col www.

題目:https://www.lydsy.com/JudgeOnline/problem.php?id=1875

有個限制是不能走回頭路,比較麻煩;

所以把矩陣中的元素設成邊的經過次數,單向邊之間就好轉移了;

最後從單向邊的經過次數得到點的路徑方案數。

代碼如下:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int const mod=45989;
int n,m,T,A,B,head[25],ct=1,tot;
struct N{
    int hd,to,next;
    N(
int h=0,int t=0,int n=0):hd(h),to(t),next(n) {} }edge[125]; struct Matrix{ int a[125][125]; Matrix(){memset(a,0,sizeof a);}// Matrix operator * (const Matrix &y) const { Matrix x; for(int i=1;i<=ct;i++) for(int k=1;k<=ct;k++) for(int j=1
;j<=ct;j++) (x.a[i][j]+=a[i][k]*y.a[k][j])%=mod; return x; } void init() { for(int i=1;i<=ct;i++)a[i][i]=1; } }tr,ans; Matrix operator ^ (Matrix x,int y) { Matrix ret; ret.init(); for(int i=y;i;i>>=1,x=x*x) if(i&1)ret=ret*x;//
i 而不是 y!!! return ret; } void add(int x,int y){edge[++ct]=N(x,y,head[x]); head[x]=ct;} int main() { scanf("%d%d%d%d%d",&n,&m,&T,&A,&B); for(int i=1,x,y;i<=m;i++) { scanf("%d%d",&x,&y); add(x,y); add(y,x); } for(int i=head[A];i;i=edge[i].next) ans.a[1][i]++; for(int i=2;i<=ct;i++)//2 for(int j=2;j<=ct;j++) if(edge[i].to==edge[j].hd && i!=(j^1)) tr.a[i][j]++;// ans=ans*(tr^(T-1)); for(int i=head[B];i;i=edge[i].next) (tot+=ans.a[1][i^1])%=mod; printf("%d",tot); return 0; }

bzoj1875 [SDOI2009]HH去散步——矩陣快速冪