loj#6074. 「2017 山东一轮集训 Day6」子序列(矩阵乘法 dp)
题意
Sol
设\(f[i][j]\)表示前\(i\)个位置中,以\(j\)为结尾的方案数。
转移的时候判断一下\(j\)是否和当前位置相同
然后发现可以用矩阵优化,可以分别求出前缀积和逆矩阵的前缀积(这题的逆矩阵炒鸡好求)
这样就可以\(n*10^3\)
发现相邻两个矩阵只有一行不同,那么其他的可以直接copy。
就可以做到\(n*10^2\)了。
#include<bits/stdc++.h>
#define Pair pair<int, int>
#define MP(x, y) make_pair(x, y)
#define fi first
#define se second
#define LL long long
#define ull unsigned long long
#define Fin(x) {freopen(#x".in","r",stdin);}
#define Fout(x) {freopen(#x".out","w",stdout);}
using namespace std;
const int MAXN = 1e5 + 10, mod = 1e9 + 7, INF = 1e9 + 10;
const double eps = 1e-9;
template <typename A, typename B> inline bool chmin(A &a, B b){if(a > b) {a = b; return 1;} return 0;}
template <typename A, typename B> inline bool chmax(A &a, B b){if(a < b) {a = b; return 1;} return 0;}
template <typename A, typename B> inline int add(A x, B y) {if(x + y < 0) return x + y + mod; return x + y >= mod ? x + y - mod : x + y;}
template <typename A, typename B> inline void add2(A &x, B y) {if(x + y < 0) x = x + y + mod; else x = (x + y >= mod ? x + y - mod : x + y);}
template <typename A, typename B> inline int mul(A x, B y) {return 1ll * x * y % mod;}
template <typename A, typename B> inline void mul2(A &x, B y) {x = (1ll * x * y % mod + mod) % mod;}
template <typename A> inline void debug(A a){cout << a << '\n';}
template <typename A> inline LL sqr(A x){return 1ll * x * x;}
template <typename A, typename B> inline LL fp(A a, B p, int md = mod) {int b = 1;while(p) {if(p & 1) b = mul(b, a);a = mul(a, a); p >>= 1;}return b;}
inline int read() {
char c = getchar(); int x = 0, f = 1;
while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
char s[MAXN];
int N, Q, a[MAXN];
struct Ma {
int m[11][11];
Ma() {
memset(m, 0, sizeof(m));
}
void init() {
for(int i = 0; i < 10; i++) m[i][i] = 1;
}
Ma operator * (const Ma &rhs) const {
Ma ans;
for(int i = 0; i < 10; i++)
for(int j = 0; j < 10; j++) {
__int128 tp = 0;
for(int k = 0; k < 10; k++)
tp += 1ll * m[i][k] * rhs.m[k][j];
ans.m[i][j] = tp % mod;
}
return ans;
}
}suf[MAXN], inv[MAXN];
int solve(int l, int r) {
Ma tmp = suf[r] * inv[l - 1];
int ans = 0;
for(int i = 0; i < 10; i++) add2(ans, tmp.m[i][9]);
return (ans - 1 + mod) % mod;
}
signed main() {
// freopen("a.in", "r", stdin);
scanf("%s", s + 1);
N = strlen(s + 1);
for(int i = 1; i <= N; i++) {
a[i] = s[i] - 'a';
suf[i].init(); inv[i].init();
for(int j = 0; j < 10; j++) suf[i].m[a[i]][j] = 1;
for(int j = 0; j < 10; j++) if(j != a[i]) inv[i].m[a[i]][j] = mod - 1;
}
suf[0].init(); inv[0].init();
for(int i = 2; i <= N; i++) suf[i] = suf[i] * suf[i - 1];
for(int i = 2; i <= N; i++) inv[i] = inv[i - 1] * inv[i];
int Q = read();
while(Q--) {
int l = read(), r = read();
cout << solve(l, r) << '\n';
}
return 0;
}
loj#6074. 「2017 山东一轮集训 Day6」子序列(矩阵乘法 dp)的更多相关文章
- LOJ #6074. 「2017 山东一轮集训 Day6」子序列
#6074. 「2017 山东一轮集训 Day6」子序列 链接 分析: 首先设f[i][j]为到第i个点,结尾字符是j的方案数,这个j一定是从i往前走,第一个出现的j,因为这个j可以代替掉前面所有j. ...
- loj#6076「2017 山东一轮集训 Day6」三元组 莫比乌斯反演 + 三元环计数
题目大意: 给定\(a, b, c\),求\(\sum \limits_{i = 1}^a \sum \limits_{j = 1}^b \sum \limits_{k = 1}^c [(i, j) ...
- LOJ#6075. 「2017 山东一轮集训 Day6」重建
题目描述: 给定一个 n个点m 条边的带权无向连通图 ,以及一个大小为k 的关键点集合S .有个人要从点s走到点t,现在可以对所有边加上一个非负整数a,问最大的a,使得加上a后,满足:s到t的最短路长 ...
- 「2017 山东一轮集训 Day6」子序列(矩阵快速幂)
/* 找出了一个dp式子 是否能够倍增优化 我推的矩阵不太一样 是 1 0 0 0 0 0 0 0 0 -1 0 0 1 0 0 0 0 0 1 0 0 1 0 0 2 求得逆矩阵大概就是 1 0 0 ...
- Loj #6069. 「2017 山东一轮集训 Day4」塔
Loj #6069. 「2017 山东一轮集训 Day4」塔 题目描述 现在有一条 $ [1, l] $ 的数轴,要在上面造 $ n $ 座塔,每座塔的坐标要两两不同,且为整点. 塔有编号,且每座塔都 ...
- Loj #6073.「2017 山东一轮集训 Day5」距离
Loj #6073.「2017 山东一轮集训 Day5」距离 Description 给定一棵 \(n\) 个点的边带权的树,以及一个排列$ p\(,有\)q $个询问,给定点 \(u, v, k\) ...
- Loj 6068. 「2017 山东一轮集训 Day4」棋盘
Loj 6068. 「2017 山东一轮集训 Day4」棋盘 题目描述 给定一个 $ n \times n $ 的棋盘,棋盘上每个位置要么为空要么为障碍.定义棋盘上两个位置 $ (x, y),(u, ...
- loj #6077. 「2017 山东一轮集训 Day7」逆序对
#6077. 「2017 山东一轮集训 Day7」逆序对 题目描述 给定 n,k n, kn,k,请求出长度为 n nn 的逆序对数恰好为 k kk 的排列的个数.答案对 109+7 10 ^ 9 ...
- LOJ #6119. 「2017 山东二轮集训 Day7」国王
Description 在某个神奇的大陆上,有一个国家,这片大陆的所有城市间的道路网可以看做是一棵树,每个城市要么是工业城市,要么是农业城市,这个国家的人认为一条路径是 exciting 的,当且仅当 ...
随机推荐
- JavaEE开发之Spring中的条件注解、组合注解与元注解
上篇博客我们详细的聊了<JavaEE开发之Spring中的多线程编程以及任务定时器详解>,本篇博客我们就来聊聊条件注解@Conditional以及组合条件.条件注解说简单点就是根据特定的条 ...
- 记录k8s:k8s1.8.4无坑离线安装
安装部署: 1. 使用vagrant 准备3太虚拟机,自己使用Vbox 准备3太也可以. 2. 按照 https://github.com/gjmzj/kubeasz 安装. 3. 使用letsenc ...
- [Swift]LeetCode662. 二叉树最大宽度 | Maximum Width of Binary Tree
Given a binary tree, write a function to get the maximum width of the given tree. The width of a tre ...
- [Swift]LeetCode923.三数之和的多种可能 | 3Sum With Multiplicity
Given an integer array A, and an integer target, return the number of tuples i, j, k such that i &l ...
- spark按某几列删除dataframe重复行
新建一个 dataframe : val conf = new SparkConf().setAppName("TTyb").setMaster("local" ...
- .NET Core中的验证组件FluentValidation的实战分享
今天有人问我能不能出一篇FluentValidation的教程,刚好今天在实现我们的.NET Core实战项目之CMS的修改密码部分的功能中有用到FluentValidation,所以就以修改用户密码 ...
- C#使用GUID
全局唯一标识符(GUID,Globally Unique Identifier) What is GUID 也称作 UUID(Universally Unique IDentifier) . GUID ...
- 面向切面编程 ( Aspect Oriented Programming with Spring )
Aspect Oriented Programming with Spring 1. 简介 AOP是与OOP不同的一种程序结构.在OOP编程中,模块的单位是class(类):然而,在AOP编程中模块的 ...
- 并发编程(三)—— ReentrantLock的用法
ReentrantLock是Java并发包中提供的一个可重入的互斥锁.ReentrantLock和synchronized在基本用法,行为语义上都是类似的,同样都具有可重入性.只不过相比原生的Sync ...
- Docker & Consul & Fabio & ASP.NET Core 2.0 微服务跨平台实践
相关博文: Ubuntu 简单安装 Docker Mac OS.Ubuntu 安装及使用 Consul Consul 服务注册与服务发现 Fabio 安装和简单使用 阅读目录: Docker 运行 C ...