1. 程式人生 > >bzoj1898: [Zjoi2005]Swamp 沼澤鱷魚

bzoj1898: [Zjoi2005]Swamp 沼澤鱷魚

mat can mem algorithm bzoj1898 tor freopen clas friend

一眼矩乘

把圖分成12個,然後直接搞。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;
const LL mod=10000;

int n;
struct Matrix
{
    LL a[60][60];
    Matrix(){}
    
void clean() { memset(a,0,sizeof(a)); } void beone() { clean(); for(int i=1;i<=n;i++)a[i][i]=1; } friend Matrix operator *(Matrix A,Matrix B) { Matrix C;C.clean(); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++)
for(int k=1;k<=n;k++) C.a[i][j]=(C.a[i][j]+(A.a[i][k]*B.a[k][j])%mod)%mod; return C; } }G[12]; LL mp[60][60]; int main() { freopen("swamp.in","r",stdin); freopen("swamp.out","w",stdout); int m,st,ed,x,y;LL K; scanf("%d%d%d%d%lld",&n,&m,&st,&ed,&K);st++,ed++; memset(mp,
0,sizeof(mp)); for(int i=1;i<=m;i++) { scanf("%d%d",&x,&y);x++,y++; mp[x][y]=1;mp[y][x]=1; } for(int k=0;k<=11;k++) for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) G[k].a[i][j]=mp[i][j]; int fish;LL p; scanf("%d",&fish); for(int i=1;i<=fish;i++) { scanf("%lld",&p); for(int j=1;j<=p;j++) { scanf("%d",&x);x++; for(int k=j-1;k<=11;k+=p) { for(int u=1;u<=n;u++)G[k].a[u][x]=0; } } } Matrix YZH;YZH.beone(); for(int i=1;i<=12;i++) { YZH=YZH*G[i%12]; if(K==i){printf("%lld\n",YZH.a[st][ed]);return 0;} } p=K/12;K%=12; Matrix ans;ans.beone(); while(p!=0) { if(p%2==1)ans=ans*YZH; YZH=YZH*YZH;p/=2; } for(int i=1;i<=K;i++)ans=ans*G[i]; printf("%lld\n",ans.a[st][ed]); return 0; }

bzoj1898: [Zjoi2005]Swamp 沼澤鱷魚