//没用

动态dp

动态dp,简称DDP,就是可修的动态规划,一般用矩阵优化

1. 前置知识:

一下默认会矩阵乘法。
矩阵维护递推,举个例子:
斐波那契数列: $ f_i = f_{i-1} + f_{i-2}$
我们可以根据造转移矩阵的方法递推。

\[\begin{bmatrix} f_{i-1} & f_{i-2}\end{bmatrix} \times \begin{bmatrix} 1 & 1\\ 1 & 0\end{bmatrix} = \begin{bmatrix} f_i & f_{i-1} \end{bmatrix} \]

且矩阵满足分配律,(注意不满足交换律),我们设转移矩阵为 \(C\),那么我们求 \(f_x\) 只需算出 \(\begin{bmatrix} 1 &1\end{bmatrix} \times C \times ... \times C\)\(x-2\)\(C\),得到结果的矩阵第一个元素既是 \(f_x\),所以我们可以进行矩阵快速幂优化为 \(O(logn)\)

I P1939 矩阵加速(数列)

模版,只需建出转移矩阵

\[\begin{bmatrix}1 & 1 & 0\\ 0 & 0 & 1\\ 1 & 0 & 0\end{bmatrix} \]

跑矩阵快速幂即可。

点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const ll mod = 1e9+7;
ll t,n;
struct Matrix{
	ll a[4][4],n,m;
	void clear(){n = m = 0;memset(a,0,sizeof a);}
	Matrix operator * (Matrix x){
		Matrix y;y.clear();y.n = n,y.m = m;
		for(int i = 1;i <= n;i++)
			for(int j = 1;j <= m;j++)
			    for(int k = 1;k <= m;k++)y.a[i][j] = (y.a[i][j] + a[i][k] * x.a[k][j]) % mod;
		return y;
	} 
}C,st,f,s;
int main(){
	scanf("%d",&t);
	st.n = 1,st.m = 3;
	st.a[1][1] = st.a[1][2] = st.a[1][3] = 1;
	C.n = C.m = 3;
	C.a[1][1] = 1,C.a[3][1] = 1,C.a[1][2] = 1,C.a[2][3] = 1; 
	while(t--){
		scanf("%lld",&n);
		if(n <= 3)printf("1\n");
		else{
			n -= 3;
			f = st,s = C;
			while(n){
				if(n & 1)f = f * s;
				s = s * s;
				n >>= 1;
			} 
			printf("%lld\n",f.a[1][1]);
		}
	}
	
	return 0;
	
}
posted @ 2024-02-03 15:55  Hao_Xu  阅读(11)  评论(0编辑  收藏  举报