zoukankan      html  css  js  c++  java
  • 【P2579】【ZJTSC05】沼泽鳄鱼

    链接:

    题目

    题目大意:

    给定一个有 (n) 个点的无向图。Jayun 从点 (s)(k) 步到 (e),但是还有一些食 Jayun 魔在周期性地在一些点间运动,如果周期为 (T),则时间 (i)(i+T) 食 Jayun 魔位于同一个点。所以为了让 Jayun 不被吃掉,要在一些时刻避开必要的点。求出有多少种不同的合法路径。

    正文:

    如果没有食 Jayun 魔,可以直接用邻接矩阵快速幂 (k) 次就行了。

    那么现在考虑有食 Jayun 魔的情况。设 (G_i) 表示时刻 (i) 去掉有食 Jayun 魔的点后的图。那么答案就是:

    [prod_{i=1}^{K}G_i ]

    又发现 (2leq Tleq4),所以经过 ( ext{lcm}(2,3,4)=12) 个时刻过后,图一定会变成原来的转移矩阵。通过这个性质就能得到:

    [prod_{i=1}^{K}G_i=left(prod_{i=1}^{12}G_i ight)^{lfloorfrac{K}{12} floor}cdotprod_{i=1}^{kmod 12}G_i ]

    这样就能 (O(n^3log K)) 解决此题了。

    代码:

    struct matrix
    {
    	ll mat[N][N];
    	int n, m;
    	matrix(){memset(mat, 0, sizeof mat);}
    	inline ll* operator [] (int b) { return mat[b];}
    }stp[13], Ans;
    
    inline matrix operator*(matrix &a, matrix &b)
    {
    	matrix c; c.n = a.n, c.m = b.m;
    	for (int i = 1; i <= a.n; i++)
    		for (int j = 1; j <= b.m; j++)
    			for (int k = 1; k <= a.m; k++)
    				c[i][j] = (c[i][j] + (a[i][k] * b[k][j]) % mod) % mod;
    	return c;
    }
    
    matrix qpow(matrix stp, ll b)
    {
    	matrix ans; ans.n = ans.m = stp.n;
    	for (int i = 1; i <= ans.n; i++)
    			ans[i][i] = 1;
    	for (; b; b >>= 1)
    	{
    		if(b & 1) ans = ans * stp; 
    		stp = stp * stp;
    	}
    	return ans;
    }
    
    int n, m, s, e, k, t;
    int w[10];
    
    int main()
    {
    	scanf ("%d%d%d%d%d", &n, &m, &s, &e, &k); 
    	s++, e++;
    	for (int i = 1; i <= m; i++)
    	{
    		int u, v;
    		scanf ("%d%d", &u, &v);
    		u++, v++;
    		for (int j = 1; j <= 12; j++)
    			stp[j][u][v] = stp[j][v][u] = 1, 
    			stp[j].n = stp[j].m = n;
    	}
    	for (scanf ("%d", &t); t--; )
    	{
    		int nfish;
    		scanf ("%d", &nfish);
    		for (int i = 1; i <= nfish; i++)
    			scanf ("%d", &w[i]), w[i]++;
    		for (int i = 1; i <= n; i++)
    			for (int j = 0; j <= 12; j++)
    				stp[j][i][w[j % nfish + 1]] = 0;
    	}
    	Ans.n = Ans.m = n;
    	for (int i = 1; i <= Ans.n; i++)
    			Ans[i][i] = 1;
    	for (int i = 1; i <= 12; i++)
    		Ans = Ans * stp[i];
    	Ans = qpow(Ans, k / 12);
    	for (int i = 1; i <= k % 12; i++)
    		Ans = Ans * stp[i];
    	printf ("%d
    ", Ans[s][e]);
    	return 0;
    }
    
  • 相关阅读:
    selenium python Chromedriver 路径
    jenkins安装
    HTMLTestRunner 报告
    夜神模拟器/逍遥模拟器--apk安装应用
    安装adb
    一个网站如何测试
    自定义控件(优酷菜单)
    SVN图标含义总结
    UDP和TCP含义,区别
    GitHub远程库的操作(设置秘钥,将本地文件上传到远程库上,克隆远程库文件到本地,Git的分支与合并,设置标签)
  • 原文地址:https://www.cnblogs.com/GJY-JURUO/p/14191481.html
Copyright © 2011-2022 走看看