zoukankan      html  css  js  c++  java
  • [洛谷P5107]能量采集

    题目大意:有一张$n(nleqslant50)$个点$m(mleqslant n(n-1))$条边的有向图,每个点还有一个自环,每个点有一个权值。每一秒钟,每个点的权值会等分成出边个数,流向出边。$q(qleqslant5 imes10^4)$次询问,每次问$t$秒时每个点的权值,只需要输出异或和

    题解:矩阵快速幂,可以构造出转移矩阵,发现直接做的复杂度是$O(qn^3log_2t)$,不可以通过。

    然后预处理转移矩阵的$2^i$次幂,就可以$O(n^2)$完成一次转移(向量乘矩阵),这样复杂度是$O(qn^2log_2t)$,看起来不可以通过本题,但其实也可以了。

    题解中说是把预处理中的二进制改成$k$进制,这样复杂度是$O(n^3klog_kt+qn^2log_kt)$

    卡点:

    C++ Code:

    #include <cstdio>
    #include <cctype>
    namespace __IO {
    	namespace R {
    		int x, ch;
    		inline int read() {
    			while (isspace(ch = getchar())) ;
    			for (x = ch & 15; isdigit(ch = getchar()); ) x = x * 10 + (ch & 15);
    			return x;
    		}
    	}
    }
    using __IO::R::read;
    
    #define maxn 50
    const int mod = 998244353;
    namespace Math {
    	inline int pw(int base, int p) {
    		static int res;
    		for (res = 1; p; p >>= 1, base = static_cast<long long> (base) * base % mod) if (p & 1) res = static_cast<long long> (res) * base % mod;
    		return res;
    	}
    	inline int inv(int x) { return pw(x, mod - 2); }
    }
    
    struct Matrix {
    #define N 50
    	int n, m;
    	int s[N][N];
    
    	inline Matrix operator * (const Matrix &rhs) {
    		Matrix res;
    		res.n = n, res.m = rhs.m;
    		for (register int i = 0; i < n; ++i) {
    			for (register int j = 0; j < rhs.m; ++j) {
    				static long long t; t = 0;
    				for (register int k = 0; k < m; ++k) t += static_cast<long long> (s[i][k]) * rhs.s[k][j] % mod;
    				res.s[i][j] = t % mod;
    			}
    		}
    		return res;
    	}
    #undef N
    } I, base[32], ans;
    
    int n, m, q;
    int oud[maxn];
    int main() {
    	n = read(), m = read(), q = read();
    	for (int i = 0; i < n; ++i) I.s[0][i] = read(), base[0].s[i][i] = 1, oud[i] = 1;
    	I.n = 1, I.m = n;
    	while (m --> 0) {
    		int a = read() - 1, b = read() - 1;
    		++base[0].s[a][b];
    		++oud[a];
    	}
    	base[0].n = base[0].m = n;
    	for (int i = 0, t; i < n; ++i) {
    		t = Math::inv(oud[i]);
    		for (int j = 0; j < n; ++j) base[0].s[i][j] = static_cast<long long> (t) * base[0].s[i][j] % mod;
    	}
    	for (int i = 1; i < 32; ++i) base[i] = base[i - 1] * base[i - 1];
    	while (q --> 0) {
    		Matrix res = I;
    		for (int i = read(); i; i &= i - 1) res = res * base[__builtin_ctz(i)];
    		int ans = 0;
    		for (int i = 0; i < n; ++i) ans ^= res.s[0][i];
    		printf("%d
    ", ans % mod);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    List--使用List作为堆栈和队列
    Range的范围
    异常处理
    关于打印输出的一些方法
    关于set的unordered特性
    面向对象
    函数
    Linux中命令备份mysql形成文件
    局域网内Linux下开启ftp服务的“曲折路”和命令复习
    linux下的apache服务自启动的几种方式
  • 原文地址:https://www.cnblogs.com/Memory-of-winter/p/10258704.html
Copyright © 2011-2022 走看看