zoukankan      html  css  js  c++  java
  • [luoguP2461] [SDOI2008]递归数列(DP + 矩阵优化)

    传送门

    本题主要是构造矩阵,我们只需要把那一段式子看成两个前缀和相减, 然后就直接矩阵连乘。

    直接对那个k+1阶矩阵快速幂即可,注意初始化矩阵为单位矩阵,即主对角线(左上到右下)都为1其他都为0。

    另外,很多量要开long long。

    #include <cstdio>
    #include <cstring>
    #define LL long long
    
    int k;
    LL b[21], c[21], n, m, p;
    
    struct Matrix
    {
    	int n, m;
    	LL a[21][21];
    	Matrix()
    	{
    		n = m = 0;
    		memset(a, 0, sizeof(a));
    	}
    }sum, sum1, sum2, t;
    
    inline Matrix operator * (Matrix x, Matrix y)
    {
    	int i, j, k;
    	Matrix ans;
    	ans.n = x.n;
    	ans.m = y.m;
    	for(i = 1; i <= x.n; i++)
    		for(j = 1; j <= y.m; j++)
    			for(k = 1; k <= y.n; k++)
    				ans.a[i][j] = (ans.a[i][j] + x.a[i][k] * y.a[k][j]) % p;
    	return ans;
    }
    
    inline Matrix operator ^ (Matrix x, LL y)
    {
    	int i;
    	Matrix ans;
    	ans.n = ans.m = k + 1;
    	for(i = 1; i <= k + 1; i++) ans.a[i][i] = 1;
    	for(; y; y >>= 1)
    	{
    		if(y & 1) ans = ans * x;
    		x = x * x;
    	}
    	return ans;
    }
    
    int main()
    {
    	int i;
    	scanf("%d", &k);
    	for(i = 1; i <= k; i++) scanf("%lld", &b[i]);
    	for(i = 1; i <= k; i++) scanf("%lld", &c[i]);
    	scanf("%lld %lld %lld", &m, &n, &p);
    	for(i = 1; i <= k; i++) b[i] %= p, c[i] %= p;
    	sum.n = sum.m = k + 1;
    	sum.a[1][1] = 1; 
    	for(i = 3; i <= k + 1; i++) sum.a[i][i - 1] = 1;
    	for(i = 2; i <= k + 1; i++) sum.a[1][i] = sum.a[2][i] = c[i - 1];
    	t.n = k + 1;
    	t.m = 1;
    	for(i = 2; i <= k + 1; i++)
    	{
    		t.a[i][1] = b[k - i + 2];
    		t.a[1][1] = (t.a[1][1] + b[i - 1]) % p;
    	}
    	if(n - k > 0)
    		sum1 = (sum ^ (n - k)) * t;
    	else for(i = 1; i <= n; i++)
    		sum1.a[1][1] = (sum1.a[1][1] + b[i]) % p;
    	if(m - k - 1 > 0)
    		sum2 = (sum ^ (m - k - 1)) * t;
    	else for(i = 1; i < m; i++)
    		sum2.a[1][1] = (sum2.a[1][1] + b[i]) % p;
    	printf("%lld
    ", ((sum1.a[1][1] - sum2.a[1][1]) % p + p) % p);
    	return 0;
    }
    

      

  • 相关阅读:
    2014年10月20----数组1
    类型--2014年10月19日
    2014年10月17----类别
    2014年10月16号--for语句实例
    2014年10月12日——运算符
    java练习题:解一元二次方程、判断闰年、判断标准身材、三个数取最大值
    Java安装与环境配置
    SQL语言增加、修改、删除数据的语法
    StringBuffer的用法(转)
    JSTL标签库简介
  • 原文地址:https://www.cnblogs.com/zhenghaotian/p/7491950.html
Copyright © 2011-2022 走看看