• 牛客14532 没有名字 (循环矩阵乘法+快速幂)


    题目链接:https://ac.nowcoder.com/acm/problem/14532

    不难看出题目是用矩阵乘法来加速的,但显然时间复杂度 (O(n^{3}logm)) 过高

    构造出矩阵后,打印出来发现,该矩阵是一个循环矩阵

    (a,b) 均为循环矩阵,则有以下性质:

    1. (a + b) 是循环矩阵
    2. (a * b) 是循环矩阵

    于是我们只要知道最初循环矩阵第一行的最终形态,就可以知道整个矩阵最终形态是什么了

    设最初的循环矩阵为 (S), (T)(S) 的转置矩阵,则
    (res[1][j] = sumlimits_{k=1}^{n} S[1][k] * T[k][j])

    时间复杂度降为 (O(n^2logm))

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int maxn = 210;
    const int M = 1000000007;
    
    int T, n, m, k;
    int c[maxn];
    
    struct Mat{
    	int a[maxn][maxn];
    	
    	Mat(){
    		for(int i = 0 ; i <= n ; ++i){
    			for(int j = 0 ; j <= n ; ++j){
    				a[i][j] = 0;
    			}
    		} 
    	}
    	
    	void build(){
    		for(int i = 1 ; i <= n ; ++i){
    			a[i][i] = 1;
    		}
    	}
    	
    	Mat operator * (const Mat &B) const{
    		Mat res;
    		for(int j = 1 ; j <= n ; ++j){
    			for(int k = 1 ; k <= n ; ++k){
    				res.a[1][j] += 1ll * a[1][k] * B.a[j][k] % M;
    				res.a[1][j] %= M;
    			}
    		} 
    		
    		for(int i = 2 ; i <= n ; ++i){
    			res.a[i][1] = res.a[i - 1][n];
    			for(int j = 2 ; j <= n ; ++j){
    				res.a[i][j] = res.a[i - 1][j - 1];
    			}
    		}
    		return res;
    	}
    };
    
    Mat qsm(Mat i, int p){
    	Mat res;
    	res.build();
    	while(p){
    		if(p & 1) res = res * i;
    		p >>= 1;
    		i = i * i;
    	}
    	return res;
    }
    
    ll read(){ ll s = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); } return s * f; }
    
    int main(){
    	T = read();
    	while(T--){
    		n = read(), m = read(), k = read();
    		for(int i = 1 ; i <= n ; ++i) c[i] = read();
    		
    		Mat ans, base;
    		for(int i = 1 ; i <= n ; ++i) ans.a[1][i] = c[i];
    		for(int i = 1 ; i <= n ; ++i){
    			for(int j = 1 ; j <= n ; ++j){
    				if((i != j) && (min(abs(j - i), n - abs(j - i)) < k)){
    					base.a[j][i] = k - min(abs(j - i), n - abs(j - i));
    				}
    			} 
    		}
    		
    		base = qsm(base, m);
    		
    		ans = ans * base;
    		
    		for(int i = 1 ; i <= n ; ++i) printf("%d ", ans.a[1][i]); printf("
    ");
    	}
    	
    	return 0;
    }
    
  • 相关阅读:
    解决百度网盘倍速需要会员问题
    npm run dev其实就是vue-cli-service serve
    git常见操作和git原理
    ajax promise三种状态
    ajax get请求
    vue2.0x methods中一个函数调用另外一个函数
    Web前端开发规范之文件存储位置规范
    大数据应用期末总评
    分布式文件系统HDFS 练习
    安装Hadoop
  • 原文地址:https://www.cnblogs.com/tuchen/p/14379829.html
Copyright © 2020-2023  润新知