zoukankan      html  css  js  c++  java
  • BZOJ1875 [SDOI2009]HH去散步 矩阵

    欢迎访问~原文出处——博客园-zhouzhendong

    去博客园看该题解


    题目传送门 - BZOJ1875


    题意概括

      在一个无向图(有重边无自环)中走,不能在经过连续经过某一条边2次。

      现在走t步,问有多少中从A到B的方案。

      答案mod 45989

      点数<=20,边数<=60,t<=230


    题解

      一开始没看到不能来回走这一个条件,所以还以为是一道水题。

      发现这个之后,思考一下,发现还是一道水题。

      如果没有这个限制条件,那么我们按照点构建矩阵,用快速幂优化就可以了。

      但是有了这个之后就稍微难一些。

      我们发现边数很少,所以我们从边开始考虑。

      我们发现可以按照边构建矩阵,表示从某条边到某条边的方案数。

      这样可以避免来回。

      边数=60*2=120,1203*log(230)可以过去的。


    代码

    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    #include <cstdlib>
    #include <cmath>
    using namespace std;
    const int N=20+5,M=60*2+5,mod=45989;
    int n,m,t,A,B;
    struct Gragh{
    	int cnt,x[M],y[M],nxt[M],fst[N];
    	void set(){
    		cnt=0;
    		memset(fst,0,sizeof fst);
    	}
    	void add(int a,int b){
    		x[++cnt]=a,y[cnt]=b,nxt[cnt]=fst[a],fst[a]=cnt;
    	}
    }g;
    struct Mat{
    	int v[M][M];
    	void set(int x){
    		memset(v,0,sizeof v);
    		if (x!=1)
    			return;
    		for (int i=1;i<=m;i++)
    			v[i][i]=1;
    	}
    	Mat operator * (Mat x){
    		Mat ans;
    		ans.set(0);
    		for (int i=1;i<=m;i++)
    			for (int j=1;j<=m;j++)
    				for (int k=1;k<=m;k++)
    					ans.v[i][j]=(ans.v[i][j]+v[i][k]*x.v[k][j])%mod;
    		return ans;
    	}
    }M0,M1,M2,M3;
    Mat MatPow(Mat x,int y){
    	Mat ans,now=x;
    	ans.set(1);
    	while (y){
    		if (y&1)
    			ans=ans*now;
    		now=now*now;
    		y>>=1;
    	}
    	return ans;
    }
    int op(int x){
    	if (x%2==0)
    		return x-1;
    	return x+1;
    }
    int main(){
    	scanf("%d%d%d%d%d",&n,&m,&t,&A,&B);
    	g.set();
    	for (int i=1,a,b;i<=m;i++){
    		scanf("%d%d",&a,&b);
    		g.add(a,b),g.add(b,a);
    	}
    	m<<=1;
    	M0.set(0);
    	for (int i=1;i<=m;i++){
    		for (int j=g.fst[g.y[i]];j;j=g.nxt[j])
    			if (j!=op(i))
    				M0.v[i][j]++;
    	}
    	M1.set(0);
    	for (int i=g.fst[A];i;i=g.nxt[i])
    		M1.v[1][i]++;
    	M2=MatPow(M0,t-1);
    	M3=M1*M2;
    	int ans=0;
    	for (int i=1;i<=m;i++)
    		if (g.y[i]==B)
    			ans=(ans+M3.v[1][i])%mod;
    	printf("%d",ans);
    	return 0;
    }
    

      

  • 相关阅读:
    证券市场主体
    证券投资基金
    1.监控系统的重要性
    1.五种世界顶级思维-20190303
    【四校联考】【比赛题解】FJ NOIP 四校联考 2017 Round 7
    【学长出题】【比赛题解】17-09-29
    【codeforces】【比赛题解】#854 CF Round #433 (Div.2)
    【codeforces】【比赛题解】#851 CF Round #432 (Div.2)
    【算法学习】三分法
    【codeforces】【比赛题解】#849 CF Round #431 (Div.2)
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/BZOJ1875.html
Copyright © 2011-2022 走看看