「CSA49」Bunny on Number Line
「CSA49」Bunny on Number Line
题目大意:有一个人从0开始走,每次可以向前走一步或者回到1,那么会产生一个位置序列,其中给出 \(k\) 个位置是好的。定义一个位置序列是好的,当前仅当其有恰好 \(n\) 个位置是好的,且最后一个位置是好的,相邻两个好的位置距离不超过 \(m\) ,求本质不同的好的序列的长度之和。两个序列本质不同当且仅当存在一个位置满足在其中一个序列中上的位置是好的,另外一个不是。
解题思路:问题转换一下,将好的位置看作 1 ,其它的位置看作 0,组成一个01字符串。那么每次往后走到一个好的位置,相当于往后接一个以1结尾的前缀,然后求这样所得的所有不同的字符串的长度之和。实际上所有1和0都是一样的,区分字符串只有每个1前面的0的数量不同。于是可以重新定义字符 \(b_i =a_i-a_{i-1}\) 。问题转化为求出所有由 \(b\) 组成的合法的不同字符串的长度之和,事实上求长度之和要用到方案数,而方案数会求了长度之和自然就能求了,所以下面就讲方案数怎么求。
考虑一个朴素的做法,令 \(dp(i,j)\) 表示当前长度为 \(i\) 的字符串末尾的字符是 \(b_j\) 的方案数,考虑 \(dp(i,j)\) 向后转移本质上是原串在某一时刻向后加了一个以 \(b_j\) 结尾的前缀,然后转移到这个前缀后面的那个字符。且这个前缀还必须与当前确定的串的后缀匹配,不然就会产生不合法的方案数。分析一下会发现这是一个kmp不断跳失配指针的过程,直接跳转移即可。不过还有几个情况要讨论一下,如果出现之前长度较长的前缀已经能转移到某个 \(c\) ,当前也要转移到 \(c\) ,此时会发现转移后的串本质是一样的,只是 \(j\) 的大小不一样,而由于长的串跳失配指针一定能包含短的串,所以只转移到较长的那个即可。另外 \(b_1\) 是一个通配符可以匹配 \([a_1,m]\) 之间的所有字符,因为其可以不断跳若干次1再走到第一个好的位置,所以要对与 \(b_1\) 的匹配加以特判。
然后这个转移求完之后同理可以利用方案数来求总长度,只需要对每个字符加权计算即可,\(b_1\) 的权是 \(\sum_{i=a_1}^mi\) ,最后矩阵快速幂优化一下这个转移即可,总复杂度 \(O(k^3logn)\) ,用 BM 可以做到 \(O(k^2)\) 。
code
/*program by mangoyang*/
#include<bits/stdc++.h>
#define inf (0x7f7f7f7f)
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
typedef long long ll;
using namespace std;
template <class T>
inline void read(T & x){
int ch = 0, f = 0; x = 0;
for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
if(f) x = -x;
}
#define int ll
#define fi first
#define se second
const int N = 105, mod = 1e9+7;
map<int, int> mp;
int nxt[N], a[N], b[N], n, m, k, ans;
inline void add(int &x, int y){ x = x + y >= mod ? x + y - mod : x + y; }
inline void del(int &x, int y){ x = x - y < 0 ? x - y + mod : x - y; }
struct Matrix{
pair<int, int> a[N][N];
inline Matrix(){ memset(a, 0, sizeof(a)); }
inline Matrix operator * (const Matrix &B) const{
Matrix ans;
for(int i = 1; i <= k; i++)
for(int j = 1; j <= k; j++)
for(int p = 1; p <= k; p++){
add(ans.a[i][j].fi, a[i][p].fi * B.a[p][j].fi % mod);
add(ans.a[i][j].se, a[i][p].fi * B.a[p][j].se % mod);
add(ans.a[i][j].se, a[i][p].se * B.a[p][j].fi % mod);
}
return ans;
}
}A, B;
inline Matrix Pow(Matrix A, int b){
Matrix ans = A; b--;
for(; b; b >>= 1, A = A * A)
if(b & 1) ans = ans * A;
return ans;
}
inline int same(int x, int y){
return y == 1 ? (b[x] >= a[1]) : (b[x] == b[y]);
}
signed main(){
read(k), read(m), read(n), nxt[0] = -1;
for(int i = 1; i <= k; i++) read(a[i]), b[i] = a[i] - a[i-1];
for(int i = 2, j = 0; i <= k; nxt[i++] = ++j)
while(~j && !same(i, j + 1)) j = nxt[j];
int tot = (m - a[1] + 1), sum = tot * (a[1] + m) / 2 % mod;
for(int i = 1; i <= k; i++){
mp.clear();
for(int p = i; p; p = nxt[p]) if(!mp[b[p+1]]){
A.a[p+1][i] = make_pair(1ll, b[p+1]);
if(b[p+1] >= a[1])
del(A.a[1][i].fi, 1), del(A.a[1][i].se, b[p+1]);
mp[b[p+1]] = 1;
}
add(A.a[1][i].fi, tot), add(A.a[1][i].se, sum);
}
if(n == 1) return cout << sum, 0;
B.a[1][1] = make_pair(tot, sum), A = Pow(A, n - 1) * B;
for(int i = 1; i <= k; i++) add(ans, A.a[i][1].se);
cout << ans;
}
「CSA49」Bunny on Number Line的更多相关文章
- 「CSA49」Card Collecting Game
「CSA49」Card Collecting Game 题目大意:有 \(n\) 种卡片,每种有 \(b_i\) 张,如果一个人集齐 \(k\) 张第 \(i\) 种卡片,那么其能获得的得分是 \(\ ...
- 「POJ3696」The Luckiest number【数论,欧拉函数】
# 题解 一道数论欧拉函数和欧拉定理的入门好题. 虽然我提交的时候POJ炸掉了,但是在hdu里面A掉了,应该是一样的吧. 首先我们需要求的这个数一定可以表示成\(\frac{(10^x-1)}{9}\ ...
- 「USACO16OPEN」「LuoguP3147」262144(区间dp
P3147 [USACO16OPEN]262144 题目描述 Bessie likes downloading games to play on her cell phone, even though ...
- 「译」JUnit 5 系列:扩展模型(Extension Model)
原文地址:http://blog.codefx.org/design/architecture/junit-5-extension-model/ 原文日期:11, Apr, 2016 译文首发:Lin ...
- 「2014-2-26」Unicode vs. UTF-8 etc.
目测是个老问题了.随便一搜,网上各种总结过.这里不辞啰嗦,尽量简洁的备忘一下. 几个链接,有道云笔记链接,都是知乎上几个问题的摘录:阮一峰的日志,1-5 还是值得参考,但是之后的部分则混淆了 Wind ...
- 「2014-2-6」TokuMX and MongoDB related materials collection
简介参考 TokuMX 和 MongoDB 各自的官方站点. ## Tokutek 最重要的特点和 marketing word 是所谓 fractal tree indexing te ...
- 「译」JavaScript 的怪癖 1:隐式类型转换
原文:JavaScript quirk 1: implicit conversion of values 译文:「译」JavaScript 的怪癖 1:隐式类型转换 译者:justjavac 零:提要 ...
- 「SCOI2015」小凸想跑步 解题报告
「SCOI2015」小凸想跑步 最开始以为和多边形的重心有关,后来发现多边形的重心没啥好玩的性质 实际上你把面积小于的不等式列出来,发现是一次的,那么就可以半平面交了 Code: #include & ...
- AC日记——「SCOI2016」背单词 LiBreOJ 2012
#2012. 「SCOI2016」背单词 思路: Orz: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 1 ...
随机推荐
- Codeforces 765F Souvenirs
time limit per test 3 seconds memory limit per test 512 megabytes input standard input output standa ...
- 数组A - 财务管理
Larry graduated this year and finally has a job. He's making a lot of money, but somehow never seems ...
- 【洛谷 P3227】 [HNOI2013]切糕(最小割)
题目链接 每层每个位置向下一层这个位置连边,流量为下一层这个位置的\(f\),源点向第一层连,流量第一层每个位置的费用,最后一层向汇点连,流量\(INF\). 这样就得到了\(P*Q\)条链,不考虑\ ...
- 【译】DTD - Entities
原文:DTD - Entities 实体用于定义XML文档中特殊字符的快捷方式. 实体主要有四种类型: 内置实体(Built-in entities) 字符实体(Character entities) ...
- Tslib触摸屏官网【转】
转自:https://github.com/kergoth/tslib C library for filtering touchscreen events tslib consists of the ...
- USB各种模式 解释
1.MTP: 通过MTP这种技术,可以把音乐传到手机里.有了U盘功能为什么还要多此一举呢?因为版权问题,MTP可以把权限文件从电脑上导过去:如果只使用手机的U盘功能,把歌的文件拷过去之后,没有权限文件 ...
- centos如何设置定时任务
1.crontab -e 打开任务列表,输入i开始编写面之后按esc退出编写默写,:wq保存退出即可. 2.关于时间格式的定义,,请使用下面的网站 https://crontab.guru/#00_0 ...
- 【转载】在GitHub上管理项目
在GitHub上管理项目 新建repository 本地目录下,在命令行里新建一个代码仓库(repository) 里面只有一个README.md 命令如下: touch README.md git ...
- java之正则表达式、日期操作
正则表达式和日期操作 正则表达式简介 正则表达式就是使用一系列预定义的特殊字符来描述一个字符串的格式规则,然后使用该格式规则匹配某个字符串是否符合格式要求. 作用:比如注册邮箱,邮箱有用户名和密码,一 ...
- HDU 1560 DNA sequence(IDA*)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1560 题目大意:给出n个字符串,让你找一个字符串使得这n个字符串都是它的子串,求最小长度. 解题思路: ...