LOJ#3104「TJOI2019」甲苯先生的字符串
题目描述
一天小甲苯得到了一条神的指示,他要把神的指示写下来,但是又不能泄露天机,所以他要用一种方法把神的指示记下来。
神的指示是一个字符串,记为字符串 \(s_1\),\(s_1\) 仅包含小写字母 \(\texttt{a-z}\)。
现在小甲苯想要写下神的指示,记为字符串 \(s_2\),\(s_2\) 仅包含小写字母 \(\texttt{a-z}\),要求 \(s_1\) 中的相邻的两个字母不能在 \(s_2\) 中相邻地出现。
现在给定 \(s_2\) 的长度,小甲苯想知道他有多少种方法可以将神的指示写下来。
输出种类数对 \(10^9 + 7\) 取模的结果。
输入格式
文件的第一行只有一个正整数 \(n\),代表字符串 \(s_2\) 的长度,\(n \le 10^{15}\)。
第二行是一个字符串,代表字符串 \(s_1\)。\(s_1\) 的长度不超过 \(100000\)。
输出格式
输出一个整数,表示小甲苯可以写出的字符串的总数。
结果对 \(10^9 + 7\) 取模。
样例
样例输入
2
ab
样例输出
675
数据范围与提示
对于 \(30\%\) 的数据,\(n ≤ 100000\);
对于 \(100\%\) 的数据,\(n ≤ 10^{15}\)。
题解
我的做法其实应该和网上的题解差不多。不过理解起来可能需要比较感性一点?
因为考虑的只有相邻两个字符,不难得知,可以把所有关系写成一个\(26\times 26\)的矩阵。
先思考一下正常怎么求解:\(f[i][j]=\sum f[i-1][k]*a[k][j]\) (\(i\)位第几位数字,\(j\)为当前放的字母,\(k\)为上一位放的字母)
那么我们把\(f[i]\)视为一个\(1\times n\)的矩阵,实际上这就是一个矩阵乘法的过程。
利用矩阵快速幂求解即可。
但是我构造的初始的矩阵有点不同:初始矩阵为一个全\(1\)的矩阵,最后统计答案时答案为\(\sum f[i][i]\)
怎么理解呢?实际上就是第一位怎么放都行,然后矩阵乘法得到的矩阵中的\(c[i][j]\),实际上就是第一个矩阵的第\(i\)行与第二个矩阵的第\(j\)列的答案。所以最终的\(f[i][i]\)即为第一位填\(i\)可以得到的方案数。
那么为什么要这么构造就不难理解了。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 100010;
const ll mod = 1e9 + 7;
ll n;
char s[N];
struct mat {
ll m[26][26];
};
mat operator * (mat a, mat b) {
mat c;
memset(c.m, 0, sizeof(c.m));
for(int i = 0; i < 26; ++i) {
for(int j = 0; j < 26; ++j) {
for(int k = 0; k < 26; ++k) {
c.m[i][j] = (c.m[i][j] + a.m[i][k] * b.m[k][j] % mod) % mod;
}
}
}
return c;
}
mat base, ans, now;
int idx(char c) {return c - 'a';}
void print(mat a) {
for(int i = 0; i < 26; ++i) {
for(int j = 0; j < 26; ++j) printf("%d ", a.m[i][j]);
puts("");
}
}
int main() {
scanf("%lld%s", &n, s + 1);
for(int i = 0; i < 26; ++i) for(int j = 0; j < 26; ++j) base.m[i][j] = 1;
int len = strlen(s + 1);
for(int i = 1; i < len; ++i) {
base.m[idx(s[i])][idx(s[i + 1])] = 0;
}
memset(ans.m, 0, sizeof(ans.m));
memset(now.m, 0, sizeof(now.m));
for(int i = 0; i < 26; ++i) ans.m[i][i] = 1;
--n;
while(n) {
if(n & 1) ans = ans * base;
base = base * base; n >>= 1;
}
for(int i = 0; i < 26; ++i) for(int j = 0; j < 26; ++j) now.m[i][j] = 1;
now = now * ans;
ll sum = 0;
for(int i = 0; i < 26; ++i) sum = (sum + now.m[i][i]) % mod;
printf("%lld\n", sum);
}
LOJ#3104「TJOI2019」甲苯先生的字符串的更多相关文章
- LG5337/BZOJ5508 「TJOI2019」甲苯先生的字符串 线性动态规划+矩阵加速
问题描述 LG5337 BZOJ5508 题解 设\(opt_{i,j}(i \in [1,n],j \in [1,26])\)代表区间\([1,i]\),结尾为\(j\)的写法. 设\(exist_ ...
- 【LOJ】#3109. 「TJOI2019」甲苯先生的线段树
LOJ#3109. 「TJOI2019」甲苯先生的线段树 发现如果枚举路径两边的长度的话,如果根节点的值是$x$,左边走了$l$,右边走了$r$ 肯定答案会是$(2^{l + 1} + 2^{r + ...
- LOJ #6436. 「PKUSC2018」神仙的游戏(字符串+NTT)
题面 LOJ #6436. 「PKUSC2018」神仙的游戏 题解 参考 yyb 的口中的长郡最强选手 租酥雨大佬的博客 ... 一开始以为 通配符匹配 就是类似于 BZOJ 4259: 残缺的字符串 ...
- LG5338/BZOJ5509/LOJ3105 「TJOI2019」甲苯先生的滚榜 Treap
问题描述 LG5338 LOJ3105 BZOJ5509 题解 建立一棵\(\mathrm{Treap}\),把原来的\(val\)换成两个值\(ac,tim\) 原来的比较\(val_a<va ...
- 「TJOI2019」甲苯先生的滚榜
题目链接 问题分析 参照数据范围,我们需要一个能够在\(O(n\log n)\)复杂度内维护有序数列的数据结构.那么平衡树是很好的选择.参考程序中使用带旋Treap. 参考程序 #pragma GCC ...
- @loj - 2106@ 「JLOI2015」有意义的字符串
目录 @description@ @solution@ @accepted code@ @details@ @description@ B 君有两个好朋友,他们叫宁宁和冉冉.有一天,冉冉遇到了一个有趣 ...
- Loj #2192. 「SHOI2014」概率充电器
Loj #2192. 「SHOI2014」概率充电器 题目描述 著名的电子产品品牌 SHOI 刚刚发布了引领世界潮流的下一代电子产品--概率充电器: 「采用全新纳米级加工技术,实现元件与导线能否通电完 ...
- Loj #3096. 「SNOI2019」数论
Loj #3096. 「SNOI2019」数论 题目描述 给出正整数 \(P, Q, T\),大小为 \(n\) 的整数集 \(A\) 和大小为 \(m\) 的整数集 \(B\),请你求出: \[ \ ...
- Loj #3093. 「BJOI2019」光线
Loj #3093. 「BJOI2019」光线 题目描述 当一束光打到一层玻璃上时,有一定比例的光会穿过这层玻璃,一定比例的光会被反射回去,剩下的光被玻璃吸收. 设对于任意 \(x\),有 \(x\t ...
随机推荐
- ztree取消之前选中状态并设置新的选中
var zTreeObject = $.fn.zTree.getZTreeObj("treeId"); var node = zTreeObject.getNodeByParam( ...
- 七、spring生命周期之初始化和销毁方法
一.通过@Bean指定初始化和销毁方法 在以往的xml中,我们是这样配置的 <bean id="exampleInitBean" class="examples.E ...
- PHP_MySQL高并发加锁事务处理
1.背景: 现在有这样的需求,插入数据时,判断test表有无username为‘mraz’的数据,无则插入,有则提示“已插入”,目的就是想只插入一条username为‘mraz’的记录. 2.一般程序 ...
- [转帖]Linux 下软链接和硬链接的区别
Linux 下软链接和硬链接的区别 http://os.51cto.com/art/201911/605267.htm 软连接 文件是小的 只是一个链接 删除和其他处理不影响 原始文件的计数 删除源文 ...
- Java中BIO,NIO,AIO的理解
在高性能的I/O体系设计中,有几个概念常常会使我们感到迷惑不解.具体如下: 1 什么是同步? 2 什么是异步? 3 什么是阻塞? 4 什么是非阻塞? 5 什么是同步阻塞? 6 什么是同步非阻塞? 7 ...
- Linux基础系统优化(一)
前言 引言没有,只有一张图. Linux的网络功能相当强悍,一时之间我们无法了解所有的网络命令,在配置服务器基础环境时,先了解下网络参数设定命令. ifconfig 查询.设置网卡和ip等参数 ifu ...
- kubernetes 实践五:Service详解
Service 是 k8s 的核心概念,通过创建Service,可以为一组具有相同功能的容器应用提供一个统一的入口地址,并且将请求负载分发到后端的各个容器应用上. Service 的定义 Servic ...
- Huawei重新开启隐藏桌面功能
在HUAWEI的EMUI系统7.0的时候我们都能发现桌面上靠手指操作的隐藏桌面的功能,像这样: 但是在之后的EMUI8.0.9.0,之后就没有办法用了.后来问了官方,这个功能确实是被去掉了.个人也很不 ...
- Docker学习笔记(一)—— 概述
1. Docker是个什么玩意 说Docker是什么之前,先来看一看Docker为什么会出现.我们知道,在学习过程中我们需要频繁地安装配置一些软件,不管是在Windows下还是在Linux,这些东西的 ...
- SpringBoot--对SpirngMVC的自动配置
SpringBoot对SpringMVC提供了许多自动配置 Inclusion of ContentNegotiatingViewResolver and BeanNameViewResolver b ...