当前位置: 首页 > news >正文

LevOJ P2080 炼金铺 II [矩阵解法]

目录

一、题目描述

二、算法标签

三、题解


题解的背景故事:其实这题题解早就发过了,但是wwj发现终于有人点赞了一年前的题解,却遭受了室友的嘲讽,“AI随便写”。wwj很不服,遂将题目给了小鲸鱼,结果被小鲸鱼薄纱。小鲸鱼使用了一种奇妙的矩阵做法,令刚在学OpenGL中复合变换的wwj很是兴奋,遂将此法写作题解。 

一、题目描述

二、算法标签

数学,线性代数(矩阵乘法)    

三、题解

这里建议先看原来的简单解法:LevOJ P2080 炼金铺 II-CSDN博客

首先将c[i]定为a[i]的初始值,d[i]定为b[i]的初始值,由于中间的操作无非就是+c[i],+d[i],+g,那么最终的答案肯定是ans=k1*c[i]+k2*d[i]+kc。由于中间我们只去记录操作,而不直接将操作结果作用在a,b上,所以ans=k1*a[i]+k2*b[i]+kc,那么问题就转化成了计算k1,k2,kc这三个系数的问题

我们定义一个三维矩阵,其第零行三个数分别表示k1,k2,kc,当进行+b[i]的操作时,就是把第一行的权值加到第零行上,当进行+g的操作时,就是把第二行的权值加到第零行上,那么当进行a[i]与b[i]的值互换的时候,就是交换了第零行和第一行(交换了操作关系)

所以我们的初始矩阵就是一个三维的单位矩阵,而最终矩阵的形式则是[k1,k2,kc],[0,k3,0],[0,0,1]

而中间将会经过一些列的矩阵变换,也就是说,我们需要提供三个变换矩阵,分别去对应炼金、嬗变、施法这三个操作。

①炼金:

首先我们知道,一个单位矩阵去乘以一个被操作矩阵,就是被操作矩阵原本的形式,而为了实现+b[i]的功能, 就需要去将被操作矩阵第一行的值累加到第零行上,这就需要将单位矩阵第零行第一列的值设置为1。最终的变换矩阵就是[1,1,0][0,1,0][0,0,1]

②嬗变:

嬗变操作将会交换a[i]和b[i]的值,也就是交换了矩阵的第零行和第一行,根据矩阵的计算法则,就需要将第零行第一列和第一行第零列置为1,同行的其他元素值为0。最终的操作矩阵就是[0,1,0][1,0,0][0,0,1]

③施法

该操作将会是单纯的累加,其实我们只需要每次将第零行第二列的值累加上g即可。不过为了统一变换,也可以设置一个操作矩阵[1,0,g][0,1,0][0,0,1]。

那么最终的结果实际上就是对于每次操作用相应的变换矩阵进行相乘即可,当执行检验操作的时候,就是取出矩阵第零行的系数,带入计算(别忘了取模就可以)。

代码:

#include<iostream>using ll = long long;
using namespace std;
const int N = 1e5 + 5;
ll mod = 1e9 + 7, g, a[N], b[N];
int q, op, x, n;struct Matrix
{ll a[3][3];Matrix(){for (int i = 0; i < 3; i++){for (int j = 0; j < 3; j++){a[i][j] = 0;}}}~Matrix() = default;Matrix operator*(const Matrix& b)const{Matrix res;for (int i = 0; i < 3; i++) {for (int j = 0; j < 3; j++) {for (int k = 0; k < 3; k++) {res.a[i][j] = (res.a[i][j] + a[i][k] * b.a[k][j]) % mod;		}}}return res;}Matrix get_identity(){Matrix res;for (int i = 0; i < 3; i++){res.a[i][i] = 1;}return res;}
};
Matrix transform, op_addb, op_swap, op_addg;void pre_work()
{transform = transform.get_identity();op_addb = transform.get_identity();op_swap = transform.get_identity();op_addg = transform.get_identity();//+bop_addb.a[0][1] = 1;//swap操作会交换第零行和第一行的值op_swap.a[0][0] = 0;op_swap.a[0][1] = 1;op_swap.a[1][0] = 1;op_swap.a[1][1] = 0;
}int main()
{std::ios::sync_with_stdio(false); cin.tie(0), cout.tie(0);pre_work();cin >> n;for (int i = 1; i <= n; i++)cin >> a[i];for (int i = 1; i <= n; i++)cin >> b[i];cin >> q;while (q--){cin>>op;if (op == 1)transform = op_addb * transform;else if (op == 2){ll res = 0;cin >> x;res = (transform.a[0][0] * a[x] % mod + transform.a[0][1] * b[x] % mod + transform.a[0][2]) % mod;cout << res << '\n';}else if (op == 3)transform = op_swap * transform;else{cin >> g;op_addg.a[0][2] = g;transform = op_addg * transform;}}return 0;
}

运行结果:

其实,毕竟需要进行矩阵的乘法运算,这个做法的运行效率并不优于先前的解法,但是,这种做法却会让人眼前一亮,权当获得一种通法开拓思路吧!

http://www.dtcms.com/a/427228.html

相关文章:

  • wordpress网站映射wordpress免费网站国外
  • 哈尔滨企业建站系统西宁建设局官方网站
  • py_innodb_page_info.py表空间分析
  • 有什么做宝宝辅食的网站吗莱阳网站开发
  • tasklet
  • 页面 HTTPS 化实战,从证书部署到真机验证的全流程(证书链、重定向、混合内容、抓包排查)
  • 北京哪家公司做网站电脑上买wordpress
  • 家用机能否做网站服务器泰安房价走势图
  • MC33PT2000控制详解七:软件代码设计1-图形化设置
  • 在租用香港服务器之前如何判断质量
  • 【高清视频】CXL 2.0 over Fibre演示和答疑 - 将内存拉到服务器10米之外
  • 【STM32项目开源】基于STM32的独居老人监护系统
  • 海外服务器怎么测试再不同地方的访问速度?
  • Linux最忙CPU组查找函数和最忙运行队列查找函数
  • 查看未知LiDAR设备的IP地址
  • iOS 0Day漏洞CVE-2025-24085相关PoC利用细节已公开
  • 网站文案框架网络推广策划书
  • 基于Chrome140的FB账号自动化——运行脚本(三)
  • 广州做网站设计镇江建筑公司排名最新
  • RHCA - CL260 | Day12:集群性能建议
  • CNN基础学习(自用)
  • Spring Boot 集成 Kafka 详解
  • MQTT数据集成
  • 网站的会员系统怎么做电商小程序价格
  • Redis 进阶:跳出缓存局限!7 大核心场景的原理与工程化实践
  • 数据结构——LinkedList和链表
  • 一学一做专题网站哈尔滨黑大主题邮局
  • 基于类的四种设计模式
  • 用ChatGPT修改论文,如何在提升质量的同时降低AI检测风险?
  • 实验指导-基于阿里云Serverless应用引l擎SAE的服务部署迀移