• HDU 5015 233 Matrix 矩阵快速幂


    题意:

    给出一个矩阵(M)的第(0)行和第(0)列,以及递推关系(M_{i,j}=M_{i-1,j}+M_{i,j-1})
    (M_{n,m} \, mod \, 10000007),其中(n leq 10, m < 2^{31})

    分析:

    注意到(n)比较小,而(m)比较大,我们可以构造矩阵,从第(k)列元素递推到第(k+1)列元素。
    具体构造方法如下:

    (n=4)为例:
    (egin{bmatrix} 10 & 0 & 0 & 0 & 0 & 1\ 10 & 1 & 0 & 0 & 0 & 1\ 10 & 1 & 1 & 0 & 0 & 1\ 10 & 1 & 1 & 1 & 0 & 1\ 10 & 1 & 1 & 1 & 1 & 1\ 0 & 0 & 0 & 0 & 0 & 1 end{bmatrix} egin{bmatrix} M_{0,k-1}\ M_{1,k-1}\ M_{2,k-1}\ M_{3,k-1}\ M_{4,k-1}\ 3 end{bmatrix} =egin{bmatrix} M_{0,k}\ M_{1,k}\ M_{2,k}\ M_{3,k}\ M_{4,k}\ 3 end{bmatrix})

    所以我们计算这个矩阵的快速幂就可得到答案。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    typedef long long LL;
    const int maxn = 15;
    const LL MOD = 10000007;
    
    LL mul_mod(LL a, LL b) { return a * b % MOD; }
    
    LL add_mod(LL& a, LL b) { a += b; if(a >= MOD) a -= MOD; }
    
    int n, m, sz;
    int a[maxn], b[maxn];
    
    struct Matrix
    {
    	LL a[15][15];
    	Matrix() { memset(a, 0, sizeof(a)); }
    	Matrix operator * (const Matrix& t) const {
    		Matrix ans;
    		for(int i = 0; i < sz; i++)
    			for(int j = 0; j < sz; j++)
    				for(int k = 0; k < sz; k++)
    					add_mod(ans.a[i][j], mul_mod(a[i][k], t.a[k][j]));
    		return ans;
    	}
    };
    
    Matrix pow_mod(Matrix a, int n) {
    	Matrix ans;
    	for(int i = 0; i < sz; i++) ans.a[i][i] = 1;
    	while(n) {
    		if(n & 1) ans = ans * a;
    		a = a * a;
    		n >>= 1;
    	}
    	return ans;
    }
    
    int main()
    {
    	while(scanf("%d%d", &n, &m) == 2) {
    		for(int i = 1; i <= n; i++) {
    			scanf("%d", a + i);
    			a[i] %= MOD;
    		}
    
    		if(m == 0) { printf("%d
    ", a[n]); continue; }
    
    		sz = n + 2;
    		b[0] = 233;
    		for(int i = 1; i <= n; i++) b[i] = (b[i-1] + a[i]) % MOD;
    		b[n + 1] = 3;
    
    		Matrix M;
    		for(int i = 0; i < sz - 1; i++) M.a[i][0] = 10;
    		for(int i = 0; i < sz; i++) M.a[i][sz-1] = 1;
    		for(int i = 1; i < sz - 1; i++)
    			for(int j = 1; j <= i; j++) M.a[i][j] = 1;
    		M = pow_mod(M, m - 1);
    
    		LL ans = 0;
    		for(int i = 0; i < sz; i++)
    			add_mod(ans, mul_mod(M.a[sz-2][i], b[i]));
    		printf("%lld
    ", ans);
    	}
    
    	return 0;
    }
    
  • 相关阅读:
    deflate树与deflate编码
    生产者消费者模式下的并发无锁环形缓冲区
    环形缓冲区的设计及其在生产者消费者模式下的使用(并发有锁环形队列)
    zeromq源码分析笔记之无锁队列ypipe_t(3)
    zeromq源码分析笔记之线程间收发命令(2)
    zeromq源码分析笔记之架构(1)
    PHP和golang差异见解
    关于助力红包随机分配思考总结
    TCP四次挥手
    TCP三次握手
  • 原文地址:https://www.cnblogs.com/AOQNRMGYXLMV/p/5254465.html
Copyright © 2020-2023  润新知