ACM训练赛赛后补题:Happy Necklace(思维+递推+矩阵快速幂)
创始人
2025-05-30 07:53:15
0

题目描述:
在这里插入图片描述
在这里插入图片描述
分析

这道题很容易就可以定性为动态规划,需要能够推出递推公式;然后观察发现n太大了,最多只能接收O(logn)的复杂度,这样的复杂度,实现的方式就是矩阵快速幂。

首先题目所说的是这一串项链里面的任何一个长度为素数的子串,都必须满足红色珠子的个数大于等于蓝色珠子的个数,那么我们可以粗略的将dp数组的状态定义为两个,f[i][j],其中i表示当前链子的长度为i,j表示这一串链子的最后一个元素(即下标i)的颜色(0表示蓝色,1表示红色)
容易得知:

(1)f[i][1]=f[i-1][1]+f[i-1][0],不论前一个珠子是红色还是蓝色,只要放上红色珠子都是可以的;
(2)f[i][0]=f[i-2][1]。可以这样想,想要在这里放上蓝色珠子,那么显然前两个元素都得是红色的珠子,因为不管是长度为2还是长度为3都必须要是红珠子数量>=蓝珠子数量,可以看做是长度为i-2,且最后一个元素为红色珠子的基础上,再加上“红蓝”这样的情况。
这里其实是有一些思维的,具体体现在,当我们在加入一个蓝色珠子的时候,前面的长度为素数的子串情况明明有很多,但是我们只考虑了长度为2的情况,这是因为,除了2以外的所有的素数,都是奇数,既然前面满足了限定条件,那么可以推断红色珠子的数量一定大于蓝色珠子的数量,因此我们只需要考虑i-2这个情况,其他的任何情况加上蓝色珠子都会满足“素数长度的子串中红色数量>=蓝色数量”。

接下来记录ans[i]=f[i][0]+f[i][1],易得
ans[i]=f[i-2][1]+f[i-1][1]+f[i-1][0]=(f[i-3][1]+f[i-3][0])+(f[i-1][1]+f[i-1][0])
=ans[i-3]+ans[i-1]

因此最后这题我们的总递推公式就记为:

f[n]=f[n-1]+f[n-3]

但是我们可以发现这题的范围太大了,也不可能开这么大数组,而且常规的递推下去是会超时的,因此考虑矩阵快速幂来实现加速,复杂度是O(logn),轻松过掉这道题。

因此我们构造一下这个矩阵,通过递推公式易得:
在这里插入图片描述

可以用快速幂的降幂思维(logn),容易得知,当幂次为奇数的时候,直接乘以这个3*3矩阵即可进入下一级别,当为偶数的时候,需要将2个原3*3矩阵先进行相乘,因为乘法运算律同样适用于矩阵,只要矩阵的相乘合理即可,不多解释了,推一下就行。

接下来就是我们的初始化问题,初始的矩阵应该设置为(f[3],f[2],f[1]),f[1]本身不存在,但是我们可以根据递推公式对其进行构造,由于f[4]=f[3]+f[1],推出f[1]=2,如此初始化即可。

代码如下:

#include
#define ll long long
using namespace std;
const int MOD=1e9+7;
struct Matrix{ll a[5][5];Matrix(){memset(a,0,sizeof(a));}
};
inline Matrix Mul(Matrix a,Matrix b){Matrix temp;for(int i=1;i<=3;++i)for(int j=1;j<=3;++j)for(int k=1;k<=3;++k)temp.a[i][j]=(temp.a[i][j]+(a.a[i][k]*b.a[k][j])%MOD)%MOD;return temp;
}
inline int fun(ll n){Matrix ans,res;ans.a[1][1]=4;ans.a[1][2]=3;ans.a[1][3]=2;res.a[1][1]=res.a[1][2]=res.a[2][3]=res.a[3][1]=1;while(n){//快速幂思想if(n&1)ans=Mul(ans,res);res=Mul(res,res);n>>=1;}return ans.a[1][1];
}
int main(){int t;cin>>t;while(t--){ll n;scanf("%lld",&n);if(n==2)printf("3\n");else if(n==3)printf("4\n");else printf("%d\n",fun(n-3));}
}

相关内容

热门资讯

linux入门---制作进度条 了解缓冲区 我们首先来看看下面的操作: 我们首先创建了一个文件并在这个文件里面添加了...
C++ 机房预约系统(六):学... 8、 学生模块 8.1 学生子菜单、登录和注销 实现步骤: 在Student.cpp的...
JAVA多线程知识整理 Java多线程基础 线程的创建和启动 继承Thread类来创建并启动 自定义Thread类的子类&#...
【洛谷 P1090】[NOIP... [NOIP2004 提高组] 合并果子 / [USACO06NOV] Fence Repair G ...
国民技术LPUART介绍 低功耗通用异步接收器(LPUART) 简介 低功耗通用异步收发器...
城乡供水一体化平台-助力乡村振... 城乡供水一体化管理系统建设方案 城乡供水一体化管理系统是运用云计算、大数据等信息化手段࿰...
程序的循环结构和random库...   第三个参数就是步长     引入文件时记得指明字符格式,否则读入不了 ...
中国版ChatGPT在哪些方面... 目录 一、中国巨大的市场需求 二、中国企业加速创新 三、中国的人工智能发展 四、企业愿景的推进 五、...
报名开启 | 共赴一场 Flu... 2023 年 1 月 25 日,Flutter Forward 大会在肯尼亚首都内罗毕...
汇编00-MASM 和 Vis... Qt源码解析 索引 汇编逆向--- MASM 和 Visual Studio入门 前提知识ÿ...
【简陋Web应用3】实现人脸比... 文章目录🍉 前情提要🌷 效果演示🥝 实现过程1. u...
前缀和与对数器与二分法 1. 前缀和 假设有一个数组,我们想大量频繁的去访问L到R这个区间的和,...
windows安装JDK步骤 一、 下载JDK安装包 下载地址:https://www.oracle.com/jav...
分治法实现合并排序(归并排序)... 🎊【数据结构与算法】专题正在持续更新中,各种数据结构的创建原理与运用✨...
在linux上安装配置node... 目录前言1,关于nodejs2,配置环境变量3,总结 前言...
Linux学习之端口、网络协议... 端口:设备与外界通讯交流的出口 网络协议:   网络协议是指计算机通信网...
Linux内核进程管理并发同步... 并发同步并发 是指在某一时间段内能够处理多个任务的能力,而 并行 是指同一时间能够处理...
opencv学习-HOG LO... 目录1. HOG(Histogram of Oriented Gradients,方向梯度直方图)1...
EEG微状态的功能意义 导读大脑的瞬时全局功能状态反映在其电场结构上。聚类分析方法一致地提取了四种头表面脑电场结构ÿ...
【Unity 手写PBR】Bu... 写在前面 前期积累: GAMES101作业7提高-实现微表面模型你需要了解的知识 【技...