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

news/2025/3/14 18:24:21/

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*wmul(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;
}

http://www.ppmy.cn/news/1373729.html

相关文章

C语言从入门到精通 第八章(用函数实现模块化程序设计)

一、函数的定义 1、概述 &#xff08;1&#xff09;函数是一个可以独立完成某个功能的语句块&#xff0c;其主要作用是将复杂程序拆成若干易于实现的子程序。 &#xff08;2&#xff09;在C语言中&#xff0c;函数分为标准函数&#xff08;又称为预定义函数&#xff09;和用…

【计算机网络】IO多路转接之epoll

文章目录 一、epoll的相关系统调用二、epoll工作原理三、epoll的优点(和 select 的缺点对应)四、epoll工作方式五、epoll服务器1.Sock.hpp2.Log.hpp3.Err.hpp4.epollServer.hpp5.epollServer.cc 一、epoll的相关系统调用 按照man手册的说法: 是为处理大批量句柄而作了改进的po…

基于OpenCV的图形分析辨认04

目录 一、前言 二、实验目的 三、实验内容 四、实验过程 一、前言 编程语言&#xff1a;Python&#xff0c;编程软件&#xff1a;vscode或pycharm&#xff0c;必备的第三方库&#xff1a;OpenCV&#xff0c;numpy&#xff0c;matplotlib&#xff0c;os等等。 关于OpenCV&…

事务(transaction)

事务&#xff0c;什么是事务&#xff0c;事务就是由单独单元的一个或多个sql语句组成&#xff0c;在这个单元中&#xff0c;每个sql语句都是相互依赖的。而整个单独单元是作为一个不可分割的整体存在&#xff0c;类似于物理当中的原子&#xff08;一种不可分割的最小单位&#…

Node.js和浏览器在JavaScript运行环境方面存在一些区别和联系

Node.js和浏览器在JavaScript运行环境方面确实存在一些区别和联系。 首先&#xff0c;让我们理解一下Node.js和浏览器的运行环境。Node.js是一个基于Chrome的V8引擎的服务器端JavaScript运行环境&#xff0c;允许开发者在服务器端运行JavaScript代码&#xff0c;并且提供了一系…

【MATLAB源码-第158期】基于matlab的海马优化算法(SHO)无人机三维路径规划,输出做短路径图和适应度曲线

操作环境&#xff1a; MATLAB 2022a 1、算法描述 海马优化器&#xff08;Sea Horse Optimizer, SHO&#xff09;是一种近年来提出的新型启发式算法&#xff0c;其设计灵感来源于海洋中海马的行为模式&#xff0c;特别是它们在寻找食物和伴侣时表现出的独特策略。海马因其独特…

【IC设计】Scala、Chisel、Chiseltest版本兼容信息

在maven仓库中精心整理的Scala、Chisel、Chiseltest的版本兼容信息&#xff0c;有了这个再也不怕sbt构建时找不到库文件了&#xff01; 目前百度上我搜不到这个资料&#xff0c;是我从maven官网上整理的&#xff0c;如果对你有用希望点点赞~ scala 2.11系列兼容的chisel版本为兼…

LabVIEW管道缺陷智能检测系统

LabVIEW管道缺陷智能检测系统 管道作为一种重要的输送手段&#xff0c;其安全运行状态对生产生活至关重要。然而&#xff0c;随着时间的推移和环境的影响&#xff0c;管道可能会出现老化、锈蚀、裂缝等多种缺陷&#xff0c;这些缺陷若不及时发现和处理&#xff0c;将严重威胁到…