矩阵乘法学习记录

这要从校赛的一个区间与非操作题说起,群里大佬用的ddp思想使其满足结合律,但是我连矩阵乘法都不会于是从头开始学习矩阵乘法。

P3390 【模板】矩阵快速幂

和快速幂一模一样,只是把数乘换成矩阵乘,只需要定义结构体矩阵然后重载一下乘法*即可。
注意:
111乘以任何数都等于这个数本身
单位矩阵乘以任何矩阵就等于这个矩阵本身

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const int N=110;
int n;
ll k;
struct node
{ll m[N][N];node(){memset(m,0,sizeof m);};node operator *(const node &b) const{node res;for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)for(int k=1;k<=n;k++)   res.m[i][j]=(res.m[i][j]+m[i][k]*b.m[k][j])%mod;return res;}
};
node qmi(node a,ll b)
{node res;for(int i=1;i<=n;i++)// 单位矩阵res.m[i][i]=1;while(b){if(b&1) res=res*a;a=a*a;b>>=1;}return res;
}
int main()
{IO;int T=1;//cin>>T;while(T--){node a;cin>>n>>k;for(int i=1;i<=n;i++)for(int j=1;j<=n;j++) cin>>a.m[i][j];node res=qmi(a,k);for(int i=1;i<=n;i++){for(int j=1;j<=n;j++) cout<<res.m[i][j]<<' ';cout<<'\n';}}return 0;
}

P1962 斐波那契数列

[0011][fn−2fn−1]=[fn−1fn]→[0011]n−2[f1f2]=[fn−1fn]\begin{bmatrix} 0 & 0 \\ 1&1 \end{bmatrix} \begin{bmatrix} f_{n-2}\\f_{n-1} \end{bmatrix}=\begin{bmatrix} f_{n-1}\\f_{n} \end{bmatrix} \to\begin{bmatrix} 0 & 0 \\ 1&1 \end{bmatrix}^{n-2} \begin{bmatrix} f_{1}\\f_{2} \end{bmatrix}=\begin{bmatrix} f_{n-1}\\f_{n} \end{bmatrix} [0101][fn2fn1]=[fn1fn][0101]n2[f1f2]=[fn1fn]
矩阵乘法满足结合律,由此可以根据上述式子进行矩阵快速乘

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const int N=110;
int sz;//矩阵大小
ll n,k;
struct node
{ll m[N][N];node(){memset(m,0,sizeof m);};node operator *(const node &b) const{node res;for(int i=1;i<=sz;i++)for(int j=1;j<=sz;j++)for(int k=1;k<=sz;k++)   res.m[i][j]=(res.m[i][j]+m[i][k]*b.m[k][j])%mod;return res;}
};
node qmi(node a,ll b)
{node res;for(int i=1;i<=sz;i++)// 单位矩阵res.m[i][i]=1;while(b){if(b&1) res=res*a;a=a*a;b>>=1;}return res;
}
int main()
{IO;int T=1;//cin>>T;while(T--){cin>>n;if(n<=2) {cout<<1<<'\n';continue;}sz=2;node a;a.m[1][1]=0,a.m[1][2]=1,a.m[2][1]=1,a.m[2][2]=1;node res=qmi(a,n-2);ll ans=0;ans=(ans+res.m[1][2]+res.m[2][2])%mod;cout<<ans<<'\n';}return 0;
}

P1939 【模板】矩阵加速(数列)和上面这个题基本一样。

P2044 [NOI2012]随机数生成器

[a101][xn−1c]=[xnc]→[a101]n[x0c]=[xnc]\begin{bmatrix} a & 1 \\ 0&1 \end{bmatrix} \begin{bmatrix} x_{n-1}\\c \end{bmatrix}=\begin{bmatrix} x_{n}\\c \end{bmatrix} \to\begin{bmatrix} a & 1 \\ 0&1 \end{bmatrix}^n \begin{bmatrix} x_{0}\\c \end{bmatrix}=\begin{bmatrix} x_{n}\\c \end{bmatrix}[a011][xn1c]=[xnc][a011]n[x0c]=[xnc]
这题比较dt的地方是两个数相乘会爆long long,于是上龟速乘防止乘积爆

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=110;
int sz;//矩阵大小
ll mod;
ll mul(ll a,ll b)//龟速乘
{ll res=0;a%=mod;while(b){if(b&1) res=(res+a)%mod;a=(a+a)%mod;b>>=1;}return res;
}
struct node
{ll m[N][N];node(){memset(m,0,sizeof m);};node operator *(const node &b) const{node res;for(int i=1;i<=sz;i++)for(int j=1;j<=sz;j++)for(int k=1;k<=sz;k++)   res.m[i][j]=(res.m[i][j]+mul(m[i][k],b.m[k][j]))%mod;return res;}
};
node qmi(node a,ll b)
{node res;for(int i=1;i<=sz;i++)// 单位矩阵res.m[i][i]=1;while(b){if(b&1) res=res*a;a=a*a;b>>=1;}return res;
}
int main()
{IO;int T=1;//cin>>T;sz=2;ll a,c,x0,n,g;while(T--){cin>>mod>>a>>c>>x0>>n>>g;node now;now.m[1][2]=now.m[2][2]=1,now.m[1][1]=a;node res=qmi(now,n);ll ans=(mul(res.m[1][1],x0)+mul(res.m[1][2],c))%mod%g;cout<<ans<<'\n';}return 0;
}

SP1716 GSS3 - Can you answer these queries III

矩阵乘法优化dp
考虑P1115 最大子段和如何做?
不难得知设计dp即可。
状态表示:fif_ifi表示以第iii个位置为结尾最大字段和,gi=max(f1,f2,…,fi)g_i=max(f_1,f_2,\dots,f_i)gi=max(f1,f2,,fi)
状态转移:fi=max(fi−1+ai,ai)f_i=max(f_{i-1}+a_i,a_i)fi=max(fi1+ai,ai)gi=max(gi−1,fi)g_i=max(g_{i-1},f_i)gi=max(gi1,fi)
最终答案即是gng_ngn

总所周知递推不满足结合律,换句话说就是你必须一步一步递推,不过矩阵乘法能够优化递推 斐波那契前 n 项和 ,而优化的方式就是使计算过程具有结合律,那么如果我们通过矩阵操作使一些不具有结合律的东西具有结合律那么我们就能用线段树维护这个东西,花费log代价显然使非常优秀的。

效仿矩阵乘法优化斐波那契的方法寻找矩阵
[ai−∞aiai0ai−∞−∞0]?[fn−1gn−10]=[fngn0]\begin{bmatrix} a_i&-\infty&a_i\\a_i&0&a_i\\ -\infty&-\infty&0\\ \end{bmatrix}? \begin{bmatrix} f_{n-1}\\g_{n-1}\\0 \end{bmatrix}= \begin{bmatrix} f_n\\g_n\\0 \end{bmatrix} aiai0aiai0?fn1gn10=fngn0
???表示一个运算
[abcd]?[ef]=[max(a+e,b+f)max(c+e,d+f)]\begin{bmatrix} a&b\\c&d \end{bmatrix}? \begin{bmatrix} e\\f \end{bmatrix}=\begin{bmatrix}max(a+e,b+f)\\max(c+e,d+f) \end{bmatrix}[acbd]?[ef]=[max(a+e,b+f)max(c+e,d+f)]
不难发现上述定义的新运算是具有结合律的!!!
对比此运算和矩阵乘法与运算不难发现:
矩阵乘法中的“乘”相当于这里的“加”而矩阵乘法中的“加”相当于这里的“max”
矩阵乘法满足结合律实际上使“乘”对“加”满足分配了,而这里“加”对“max”同样满足分配率于是新运算具有结合律。

满足结合律并且区间查询单点修改无疑线段树,只需要每个节点维护一个矩阵即可。

考虑答案在哪?
定义:
Ai=[ai−∞aiai0ai−∞−∞0]A_i= \begin{bmatrix} a_i&-\infty&a_i\\a_i&0&a_i\\ -\infty&-\infty&0\\ \end{bmatrix}Ai=aiai0aiai0
Bi=A1?A2?…?AiB_i= A_1?A_2?\dots\ ?A_i Bi=A1?A2? ?Ai
那么再看此题 P1115 最大子段和,不难得出
Bn?[000]=[fngn0]B_n ?\begin{bmatrix} 0\\0\\0 \end{bmatrix}=\begin{bmatrix} f_n\\g_n\\0 \end{bmatrix}Bn?000=fngn0
答案就是gng_ngn,不难发现答案就蕴藏着BnB_nBn矩阵中,分析一下不难得知如果Bn=[b11b12b12b21b22b23b31b32b33]B_n=\begin{bmatrix} b_{11}&b_{12}&b_{12}\\b_{21}&b_{22}&b_{23}\\ b_{31}&b_{32}&b_{33}\\ \end{bmatrix}Bn=b11b21b31b12b22b32b12b23b33那么答案就是max(b21,b23)max(b_{21},b_{23})max(b21,b23)

而本题有了之前的工作只需要套个线段树就是基本的区间修改单点查询问题。

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn=3,INF=0x3f3f3f3f;
const int N=50010;//投机取巧
int n,q,a;
int sz;//矩阵大小
struct node
{int l,r;int m[maxn][maxn];node(){l=r=0;memset(m,0,sizeof m);};node operator *(const node &b) const{node res;res.l=l,res.r=b.r;memset(res.m,-0x3f,sizeof res.m);for(int i=0;i<sz;i++)for(int j=0;j<sz;j++)for(int k=0;k<sz;k++)   res.m[i][j]=max(res.m[i][j],m[i][k]+b.m[k][j]);return res;}int ans(){return max(m[1][0],m[1][2]);}
}tree[N<<2];
void pushup(int u)
{tree[u]=tree[u<<1]*tree[u<<1|1];
}
void build(int u,int l,int r)
{if(l==r){cin>>a;//这样输入省空间tree[u].l=tree[u].r=r;tree[u].m[0][0]=tree[u].m[1][0]=tree[u].m[0][2]=tree[u].m[1][2]=a;tree[u].m[0][1]=tree[u].m[2][0]=tree[u].m[2][1]=-INF;return;}int mid=l+r>>1;build(u<<1,l,mid);build(u<<1|1,mid+1,r);pushup(u);
}
void modify(int u,int pos,int x)
{if(tree[u].l==tree[u].r){tree[u].m[0][0]=tree[u].m[1][0]=tree[u].m[0][2]=tree[u].m[1][2]=x;return;}int mid=tree[u].l+tree[u].r>>1;if(pos<=mid) modify(u<<1,pos,x);else modify(u<<1|1,pos,x);pushup(u);
}
node query(int u,int l,int r)
{if(tree[u].l>=l&&tree[u].r<=r) return tree[u];int mid=tree[u].l+tree[u].r>>1;if(r<=mid) return query(u<<1,l,r);else if(l>mid)return query(u<<1|1,l,r);else return query(u<<1,l,r)*query(u<<1|1,l,r);
}
int main()
{IO;cin>>n;sz=3;build(1,1,n);cin>>q;while(q--){int op,x,y;cin>>op>>x>>y;if(op==1){if(x>y) swap(x,y);cout<<query(1,x,y).ans()<<'\n';}elsemodify(1,x,y);}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/319377.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

51nod1600-Simple KMP【SAM,树链剖分】

正题 题目链接:http://www.51nod.com/Challenge/Problem.html#problemId1600 题目大意 给出一个字符串sss&#xff0c;每次在最后插入一个字符后求它的所有分别子串构出的failfailfail树的深度和。 1≤Q≤1051\leq Q\leq 10^51≤Q≤105 解题思路 考虑两个相等的子串长度为le…

课程 预编译框架,开发高性能应用 - 微软技术暨生态大会 2018

微软技术暨生态大会&#xff08;Tech Summit&#xff09;&#xff0c;2018 年在上海世博中心召开。这是最后一次的 Tech Summit 了&#xff1b;明年开始&#xff0c;中国大陆地区就要和其他国家和地区一样&#xff0c;进行全球 Ignite Tour 了。我也有幸成为分会场讲师团队的一…

【DP】方格计数(nowcoder 20107-B)

正题 nowcoder 20107-B 题目大意 在一个H*W的平面上&#xff0c;选择N个点&#xff08;坐标为非负整数&#xff09;&#xff0c;使得每个点之间的距离大于D&#xff0c;问你有多少种方案 解题思路 设fi,j,kf_{i,j,k}fi,j,k​为有i个格子&#xff0c;选择k个格子&#xff0c;…

YbtOJ#853-平面标记【整体二分,凸壳】

正题 题目链接:http://www.ybtoj.com.cn/contest/119/problem/3 题目大意 给出nnn个点(xi,yi)(x_i,y_i)(xi​,yi​)&#xff0c;mmm次给出(ki,ai)(k_i,a_i)(ki​,ai​)表示标记所有满足 yj>kixjaiy_j>\frac{k_i}{x_j^{a_i}}yj​>xjai​​ki​​的未标记点 求每个点…

Ocelot简易教程(五)之集成IdentityServer认证以及授权

最近比较懒&#xff08;编者注&#xff1a;作者不是真懒&#xff0c;而是在憋大招&#xff0c;他最近实现了把Ocelot的配置使用数据库存储&#xff09;&#xff0c;所以隔了N天才来继续更新第五篇Ocelot简易教程&#xff0c;本篇教程会先简单介绍下官方文档记录的内容然后在前几…

【启发式合并】【dfs】树数树(nowcoder 20107-C)

正题 nowcoder 20107-C 题目大意 给一棵树&#xff0c;让你构造一个序列a&#xff0c;使得a中的数互不相等&#xff0c;且相邻点是祖先的关系&#xff0c;回答序列最长长度 解题思路 书中的每个点可以把字数的两个序列连起来 考虑维护一个堆&#xff0c;存子树中的序列&…

CF848E-Days of Floral Colours【dp,分治NTT】

正题 题目链接:https://www.luogu.com.cn/problem/CF848E 题目大意 2n2n2n个花排成一个圆环&#xff0c;nnn种颜色每种两个&#xff0c;要求两个相同颜色之间最小距离为1,21,21,2或nnn。 对于一种染色方案的权值为&#xff1a;删除掉距离为nnn的颜色后&#xff0c;剩下的连续…

2020 China Collegiate Programming Contest Qinhuangdao Site 补题部分

已经补AEFGK E. Exam Results 枚举二分动态开点权值线段树O(nlogN)O(nlogN)O(nlogN) 智商太低&#xff0c;想不到什么贪心只能暴力数据结构维护 对于所有学生的最高成绩只可能是ai(1≤i≤n)a_i(1\leq i\leq n)ai​(1≤i≤n)或者最大的bib_ibi​&#xff0c;对于后面一种情况…

CCPC Training Class

杭电oj 题意&#xff1a; 字符串中出现次数最多的字母的次数是多少&#xff1f; 题解&#xff1a; 题目看不懂。。。又臭又长 懒得看。。 但是仔细看样例就会发现。。其实考的很简单 比赛时这题是我做的&#xff0c;以下为考试原码 代码&#xff1a; #include<string&…

【交互】Omkar and the Meaning of Life(CF-1586D)

正题 CF-1586D 题目大意 有一个大小为n的数列a&#xff0c;你可以进行最多2*n次查询 对于每次查询&#xff0c;你要给出一个大小为n的数列b&#xff0c;ciaibic_ia_ib_ici​ai​bi​&#xff0c;题目会回答c中出现次数大于2的数的最早出现位置 现在让你得出a数组 解题思路 …

ASP.NET Core 集成测试中结合 WebApplicationFactory 使用 SQLite 内存数据库

SQLite 内存数据库&#xff08;in-memory database&#xff09;的连接字符串是 Data Source:memory: &#xff0c;它的特点是数据库连接一关闭&#xff0c;数据库就会被删除。而使用 services.AddDbContext 通过连接字符串配置 EF Core 时&#xff0c;EF Core 会在每次查询或…

P4389-付公主的背包【生成函数,多项式exp】

正题 题目链接:https://www.luogu.com.cn/problem/P4389 题目大意 nnn种物品&#xff0c;第iii种大小为viv_ivi​&#xff0c;数量无限。对于每个s∈[1,m]s\in[1,m]s∈[1,m]求刚好填满sss容量的方案数。 1≤n,m≤1051\leq n,m\leq 10^51≤n,m≤105 解题思路 统计和为一定值的…

mex性质学习

E.Complicated Computations 如果一个区间的mexamexamexa&#xff0c;满足以下条件&#xff1a; 区间未出现aaa区间出现1→a−11\to a-11→a−1 因此若考虑是否存在一个区间的mex值是aaa&#xff0c;我们尝试把整个区间以aaa为端点划分成若干段&#xff0c;只要每一段内&…

Cows

题目 题意: 有一群牛&#xff0c;每个牛有两个属性值[S,E]&#xff0c;如果牛i和牛j属性值满足Si < Sj 且 Ej < Ei 且 Ei - Si > Ej - Sj&#xff0c;牛i比牛j强壮&#xff0c;输出每个牛比自己强壮的牛的数量。 题解&#xff1a; 我们可以把[S,E]看作坐标&#x…

【SAM】差异(P4248)

正题 P4248 题目大意 设TiT_iTi​为第i个字符开始的后缀&#xff0c;求&#xff1a; ∑i1n∑ji1nlen(Ti)len(Tj)−2lcp(Ti,Tj)\sum_{i1}^n \sum_{ji1}^n len(T_i)len(T_j)-2\times lcp(T_i,T_j)i1∑n​ji1∑n​len(Ti​)len(Tj​)−2lcp(Ti​,Tj​) 解题思路 用SAM建立paren…

P4345-[SHOI2015]超能粒子炮·改【Lucas定理,类欧】

正题 题目链接:https://www.luogu.com.cn/problem/P4345 题目大意 TTT组询问&#xff0c;给出n,kn,kn,k求 ∑i0k(ni)\sum_{i0}^{k}\binom{n}{i}i0∑k​(in​) 对233323332333取模的值 1≤T≤105,1≤k≤n≤10181\leq T\leq 10^5,1\leq k\leq n\leq 10^{18}1≤T≤105,1≤k≤n≤1…

AServer - 基于Asp.net core Kestrel的超迷你http服务器

AServer是基于ASP.NET Core Kestrel封装的一个超迷你http服务器。它可以集成进你的Core程序里&#xff0c;用来快速的响应Http请求&#xff0c;而不需要集成整个ASP.NET Core MVC 框架。一&#xff1a;什么是ASever&#xff1f;AServer就像它的名字一样&#xff0c;Just a serv…

特征根是复数的二阶微分方程

考虑如下微分方程d2ydx2a1dydxa2x0\frac{d^2y}{dx^2}a_1\frac{dy}{dx}a_2x0dx2d2y​a1​dxdy​a2​x0 众所周知&#xff0c;一般求得二阶常系数线性微分方程的通常由以下步骤 根据微分方程写出它的特征方程λ2a1λa20\lambda^2a_1\lambdaa_20λ2a1​λa2​0求解特征方程的两个…

Buy and Resell 2018中国大学生程序设计竞赛 - 网络选拔赛

题目 题意&#xff1a; n个宝石&#xff0c;宝石的买入或卖出价格固定&#xff0c;一天只能到一个珠宝商店&#xff08;从左到右&#xff09;&#xff0c;问最大利润是多少&#xff1f;在保证最大利润的同时最少交换次数是多少&#xff1f; 题解&#xff1a; 题目有两问&am…

基于Service fabric + Ocelot + Identity Server4 + 52ABP 的案例展示

10.24-27 大会Microsoft Tech Summit 2018 在上海举办&#xff0c;我 有幸受邀成为这场大会的讲师。Microsoft Tech Summit 2018 微软技术暨生态大会将于10月24日至27日在上海世博中心举行&#xff0c;这也会是国内举办的最后一届 Tech Summit&#xff0c;2019 年开始会以 Micr…