CCF CSP 202006-4 1246 (100分详细题解,矩阵乘法+快速幂)

202006-4 1246 (100分详细题解,矩阵乘法+快速幂)

在这里插入图片描述

可以先看下csp官方的思路讲解,大思路是状态转移,先看下面s<=2的情况

1 -> 2
2 -> 4
4 -> 16
6 -> 6 64 4
16 -> 26(不考虑26464的原因是,16可以拆分为16,而1->2 , 6-> 64, 6, 4,去除冗余解)
... 详细见尾部代码

s<=2共有14个数字,故可以将这个14个数字离散化到0~13,形成14*14转移矩阵,随后根据线性代数矩阵的结合律,这14个数字构成一个行向量a,可以使用矩阵快速幂,快速得到这14个数字出现的次数。由于向量a初始时为{1,0…0},故代码中直接由res矩阵的第0行充当。

当s>2时,可以进行倒推,如:464 上一次由 26操作而来。同时考虑到题目给的s是一个部分数字串,故可能无法直接倒推回s=2,故s在整个序列的情况,可能分为s前面是1,s前面是6,或者s前面不是1或6, 因为4->16 6->64,都会产生两位,所以s的首个数字可能是16中的6,以及64中的6,由于s只是其中的一部分,所以我们要在前面补上1和6。你可能回想为什么不在后面补1和6,其实也考虑了,不过在代码中用i + 1 == str.size()来解决了。

#include <bits/stdc++.h>

using namespace std;

typedef long long LL;
const int N = 14, MOD = 998244353;

int n;
string S;
int id[100];        // id[x]将x映射到0~13
vector<int> vers{
    1, 2, 4, 6, 16, 26, 41, 42, 44,
    46, 61, 62, 64, 66
};
// 上面的数字进行运算后可以得出下面的贡献,两位数字的运算后的数字只有一个
// 如16->26(不考虑2,6,4,64的原因是,16可以拆分为1和6,而1->2 , 6->64, 6, 4)
// 故两位数字运算后只转移到前一位数字幂的后一位和后一位数字幂的前一位

// 当s的长度大于2时,我们可以根据转移的规律,逆推到s只有两位的情况。
// s在整个序列的情况,可能分为s前面是1,s前面是6,或者s前面不是1或6.
// 因为4->16 6->64,都会产生两位,所以s的首个数字可能是16中的6,以及64中的6,由于s只是其中的一部分,所以我们要补上1和6
vector<vector<int>> g{
    {2}, {4}, {1, 6, 16}, {6, 4, 64}, {26},
    {46}, {62}, {64}, {61}, {66}, {42},
    {44}, {41}, {46}
};
int tr[N][N];       // tr的第j列是对ver[j]的贡献

void init() {
    memset(id, -1, sizeof id);
    for (int i = 0; i < N; i++) id[vers[i]] = i;        // 映射
    //求转移矩阵
    for (int i = 0; i < N; i++)
        for (auto x : g[i])
            tr[i][id[x]] ++;
}

void mul(int c[][N], int a[][N], int b[][N]) {
    static int tmp[N][N];
    memset(tmp, 0, sizeof tmp);
    for (int i = 0; i < N; i++)     // 行
        for (int j = 0; j < N; j++)     // 列
            for (int k = 0; k < N; k++)     // 行×列
                tmp[i][j] = (tmp[i][j] + (LL)a[i][k] * b[k][j]) % MOD;
    memcpy(c, tmp, sizeof tmp);
}

int qmi(int k, int id) {
    if (id == -1) return 0;
    int res[N][N] = { 0 }, w[N][N];
    memcpy(w, tr, sizeof w);
    res[0][0] = 1;      // 初始,使用res的首行充当0时刻的行向量

    while (k) {
        if (k & 1) mul(res, res, w); //res=res*w
        mul(w, w, w);   // w=w*w;
        k >>= 1;
    }
    return res[0][id];
}

string get(string str) {
    string res;
    for (int i = 0; i < str.size(); i++)
        if (str[i] == '2') res += '1';
        else if (str[i] == '4') res += '2';
        else if (str[i] == '1') {
            if (i + 1 == str.size() || str[i + 1] == '6') res += '4', i++;
            else return "";
        } else {
            if (i + 1 == str.size() || str[i + 1] == '4') res += '6', i++;
            else return "";
        }
    return res;
}

int dfs(int k, string& str) {
    if (str.size() <= 2) return qmi(k, id[stoi(str)]);
    int res = 0;
    for (string s : {"", "1", "6"}) {
        auto t = get(s + str);
        if (t.size()) res = (res + dfs(k - 1, t)) % MOD;        // !!!!!!!
    }
    return res;
}

int main() {
    init();
    cin >> n >> S;
    cout << dfs(n, S) << endl;
    return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

“计算机界三大神书”之一 ——SICP【赠书活动】

目录 前言一、SICP简介二、改编本SCIP JS福利总结 前言 《计算机程序的构造和解释》&#xff08;Structure and Interpretation of Computer Programs&#xff0c;简记为SICP&#xff09;是MIT的基础课教材&#xff0c;出版后引起计算机教育界的广泛关注&#xff0c;对推动全世…

Java开发必须掌握,java高级工程师面试类的加载

前言 这些算法&#xff0c;都是小编一点一点看的大佬们的方法&#xff0c;自己积累的. 如果有什么描述的不对 点击领取2024完整开源项目《一线大厂Java面试题解析后端开发学习笔记最新架构讲解视频实战项目源码讲义》 的地方还望大佬赐教 多交流才能进步&#xff0c;加油&#…

Apache POI 解析和处理Excel

摘要&#xff1a;由于开发需要批量导入Excel中的数据&#xff0c;使用了Apache POI库&#xff0c;记录下使用过程 1. 背景 Java 中操作 Excel 文件的库常用的有Apache POI 和阿里巴巴的 EasyExcel 。Apache POI 是一个功能比较全面的 Java 库&#xff0c;适合处理复杂的 Offi…

errno 和 strerror函数

今天写了一个很简单的代码&#xff0c;编译时没啥错误和警告&#xff08;主要编译选项没开启警告&#xff09;&#xff0c;然后运行时居然 segmentation fault&#xff0c;把我给看傻了&#xff0c;代码如下&#xff1a; #include <stdio.h> #include <stdlib.h> …

2024护网面试题精选(一)

0x00.基础漏洞篇 00-TOP10漏洞 1.SQL注入 2.失效的身份认证和会话管理 3.跨站脚本攻击XSS 4.直接引用不安全的对象 5.安全配置错误 6.敏感信息泄露 7.缺少功能级的访问控制 8.跨站请求伪造CSRF 9.实验含有已知漏洞的组件 10.未验证的重定向和转发 01-SQL注入漏洞 …

PackagesNotFoundError:学习利用报错信息找到解决方法

反思&#xff1a;之前看到报错经常是直接复制报错信息去网上搜&#xff0c;但很多情况下报错信息里其实就给出了解决方案 报错信息&#xff1a; Collecting package metadata (current_repodata.json): done Solving environment: unsuccessful initial attempt using frozen …

关于Mybatis-Plus报错 Not Found TableInfoCache 解决办法

0. 接口结构&#xff1a;1. 方法报错&#xff1a;2. 解决方法&#xff1a;3. 原因分析&#xff1a; 0. 接口结构&#xff1a; 【接口】&#xff1a; public interface PurchaseOrderService extends IService<PurchaseOrder> {}【接口实现类】&#xff1a; public cla…

某多多anti_token(先水个文后续会完善)第一部分

声明: 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;不提供完整代码&#xff0c;抓包内容、敏感网址、数据接口等均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01;wx a15018…

某酷ckey140逆向(之前下架了重新上传补发)

声明: 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;不提供完整代码&#xff0c;抓包内容、敏感网址、数据接口等均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01;wx a15018…

[R] Underline your idea with ggplot2

Preview: # 介绍&#xff1a;之前的教程中&#xff0c;我们学习了如何使条形图或直方图看起来更好 比如&#xff1a; 1. How to select a graph calibrate the geom part 2. How to select variables calibrate the aes part 3. How to add a title calibrate the labs …

【Mybatis】批量映射优化 分页插件PageHelper 逆向工程插件MybatisX

文章目录 一、Mapper批量映射优化二、插件和分页插件PageHelper2.1 插件机制和PageHelper插件介绍2.2 PageHelper插件使用 三、逆向工程和MybatisX插件3.1 ORM思维介绍3.2 逆向工程3.3 逆向工程插件MyBatisX使用 总结 一、Mapper批量映射优化 需求: Mapper 配置文件很多时&…

16:00面试,16:08就出来了,问的问题过于变态了。。。

从小厂出来&#xff0c;没想到在另一家公司又寄了。 到这家公司开始上班&#xff0c;加班是每天必不可少的&#xff0c;看在钱给的比较多的份上&#xff0c;就不太计较了。没想到2月一纸通知&#xff0c;所有人不准加班&#xff0c;加班费不仅没有了&#xff0c;薪资还要降40%…

Sparse A*算法的时间复杂度

Sparse A*(SAS)算法是A*算法的变型算法&#xff0c;下面将结合A*算法的流程分析SAS的时间复杂度。对于SAS算法而言&#xff0c;其航迹规划的时间 T T T主要由两部分组成&#xff1a; T s T_s Ts​&#xff1a;在当前结点扩展可行子结点的时间&#xff1b; T 0 T_0 T0​&#…

Qt QPainter的使用方法

重点&#xff1a; 1.QPainter在QWidget窗口的paintEvent中使用。 2.QPainter通常涉及到设置画笔、设置画刷、绘图&#xff08;QPen、QBrush、drawxx&#xff09;三个流程。 class Widget : public QWidget {Q_OBJECTprotected:void paintEvent(QPaintEvent *event) Q_DEC…

基于51单片机的四位并行数据主从机传输设计

基于51单片机的四位并行数据主从机传输设计[proteus仿真] 主从机通信系统这个题目算是课程设计和毕业设计中常见的题目了&#xff0c;本期是一个基于51单片机的四位并行数据主从机传输设计 需要的源文件和程序的小伙伴可以关注公众号【阿目分享嵌入式】&#xff0c;赞赏任意文…

机器学习---数据分割

之前的文章中写过&#xff0c;我们可以通过实验测试来对学习器的泛化误差进行评估并进而做出选择。 为此&#xff0c;需使用一个“测试集"(testing set)来测试学习器对新样本的判别能力&#xff0c;然后以测试集上的“测 试误差”(testing error)作为泛化误差的近似。通…

操作系统系列学习——内核级线程实现

文章目录 前言内核级线程实现 前言 一个本硕双非的小菜鸡&#xff0c;备战24年秋招&#xff0c;计划学习操作系统并完成6.0S81&#xff0c;加油&#xff01; 本文总结自B站【哈工大】操作系统 李治军&#xff08;全32讲&#xff09; 老师课程讲的非常好&#xff0c;感谢 【哈工…

Linux第71步_将linux中的多个文件编译成一个驱动模块

学习目的&#xff1a;采用旧字符设备测试linux系统点灯&#xff0c;进一步熟悉其设计原理。采用多文件参与编译&#xff0c;深度学习编写Makefile&#xff0c;有利于实现驱动模块化设计。 1、创建MyOldLED目录 输入“cd /home/zgq/linux/Linux_Drivers/回车” 切换到“/home…

softmax和sigmoid的区别

sigmoid 公式&#xff1a; s i g m o i d ( x ) 1 1 e − x sigmoid(x) \frac{1}{1 e^{-x}} sigmoid(x)1e−x1​ 函数曲线如下&#xff1a; 导数公式&#xff1a; f ( x ) ′ e − x ( 1 e − x ) 2 f ( x ) ( 1 − f ( x ) ) f(x)\prime \frac{ e^{-x}}{(1 e^{-x})…

备战蓝桥杯————二分搜索(一)

引言 一、二分查找 基本概念 代码框架 二、二分查找 题目描述 解题思路及代码 结果展示 三、寻找左侧边界的二分搜索 使用背景 基本代码 引言 在计算机科学的世界里&#xff0c;二分查找算法无疑是一种经典且强大的工具。它以其高效的性能&#xff0c;在有序数据集中…