zoukankan      html  css  js  c++  java
  • bzoj4128 Matrix 矩阵 BSGS

    题目传送门

    https://lydsy.com/JudgeOnline/problem.php?id=4128

    题解

    想了十分钟没有任何思路。

    然后一眼瞥见一句话“数据保证在 (p) 内有解”,还有 (p leq 19997)...

    那么这道题不就是把同余类 BSGS 里面的数换成矩阵嘛。

    问题就是怎么快速判断两个矩阵是否相等。哈希呗。

    然后就没有然后了。


    这里推荐写哪种不需要求逆的版本的 BSGS。

    #include<bits/stdc++.h>
    #include<tr1/unordered_map>
    
    #define fec(i, x, y) (int i = head[x], y = g[i].to; i; i = g[i].ne, y = g[i].to)
    #define dbg(...) fprintf(stderr, __VA_ARGS__)
    #define File(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
    #define fi first
    #define se second
    #define pb push_back
    
    template<typename A, typename B> inline char smax(A &a, const B &b) {return a < b ? a = b, 1 : 0;}
    template<typename A, typename B> inline char smin(A &a, const B &b) {return b < a ? a = b, 1 : 0;}
    
    typedef long long ll; typedef unsigned long long ull; typedef std::pair<int, int> pii;
    
    template<typename I> inline void read(I &x) {
    	int f = 0, c;
    	while (!isdigit(c = getchar())) c == '-' ? f = 1 : 0;
    	x = c & 15;
    	while (isdigit(c = getchar())) x = (x << 1) + (x << 3) + (c & 15);
    	f ? x = -x : 0;
    }
    
    const int N = 70 + 7;
    const int base = 1997;
    
    int n, P;
    std::tr1::unordered_map<ull, int> mp;
    
    inline int smod(int x) { return x >= P ? x - P : x; }
    inline void sadd(int &x, const int &y) { x += y; x >= P ? x -= P : x; }
    inline int fpow(int x, int y) {
    	int ans = 1;
    	for (; y; y >>= 1, x = (ll)x * x % P) if (y & 1) ans = (ll)ans * x % P;
    	return ans;
    }
    
    struct Matrix {
    	int a[N][N];
    	
    	inline Matrix() { memset(a, 0, sizeof(a)); }
    	inline Matrix(const int &x) {
    		memset(a, 0, sizeof(a));
    		for (int i = 1; i <= n; ++i) a[i][i] = x;
    	}
    	
    	inline Matrix operator * (const Matrix &b) {
    		Matrix c;
    		for (int k = 1; k <= n; ++k)
    			for (int i = 1; i <= n; ++i)
    				for (int j = 1; j <= n; ++j) sadd(c.a[i][j], (ll)a[i][k] * b.a[k][j] % P);
    		return c;
    	}
    	inline ull hash() {
    		ull ha = 0;
    		for (int i = 1; i <= n; ++i)
    			for (int j = 1; j <= n; ++j)
    				ha = ha * base + (a[i][j] + 1);
    		return ha;
    	}
    } A, B;
    
    inline Matrix fpow(Matrix x, int y) {
    	Matrix ans(1);
    	for (; y; y >>= 1, x = x * x) if (y & 1) ans = ans * x;
    	return ans;
    }
    
    inline int bsgs() {
    	int m = sqrt(P);
    	Matrix C = B, e;
    	for (int i = 0; i < m; ++i, C = C * A) mp[C.hash()] = i;
    	e = C = fpow(A, m);
    	for (int i = 1; ; ++i, C = C * e) if (mp.count(C.hash())) return i * m - mp[C.hash()];
    }
    
    inline void work() {
    	printf("%d
    ", bsgs());
    }
    
    inline void init() {
    	read(n), read(P);
    	for (int i = 1; i <= n; ++i)
    		for (int j = 1; j <= n; ++j)
    			read(A.a[i][j]);
    	for (int i = 1; i <= n; ++i)
    		for (int j = 1; j <= n; ++j)
    			read(B.a[i][j]);
    }
    
    int main() {
    #ifdef hzhkk
    	freopen("hkk.in", "r", stdin);
    #endif
    	init();
    	work();
    	fclose(stdin), fclose(stdout);
    	return 0;
    }
    
  • 相关阅读:
    进程池,线程池,协程,gevent模块,协程实现单线程服务端与多线程客户端通信,IO模型
    线程相关 GIL queue event 死锁与递归锁 信号量l
    生产者消费者模型 线程相关
    进程的开启方式 进程的join方法 进程间的内存隔离 其他相关方法 守护进程 互斥锁
    udp协议 及相关 利用tcp上传文件 socketserver服务
    socket套接字 tcp协议下的粘包处理
    常用模块的完善 random shutil shevle 三流 logging
    day 29 元类
    Django入门
    MySQL多表查询
  • 原文地址:https://www.cnblogs.com/hankeke/p/bzoj4128.html
Copyright © 2011-2022 走看看