【ARC077F】SS
Description
如果某个串可以由两个一样的串前后连接得到,我们就称之为“偶串”。比如说“xyzxyz”和“aaaaaa”是偶串,而“ababab”和“xyzxy”则不是偶串。
对于一个非空串\(S\),我们定义\(f(S)\)是在\(S\)后面添加一些字符得到的最短偶串。比如\(f(\)'abaaba'\()=\)'abaababaab'。容易证明,对于一个非空串\(S\),\(f(S)\)是唯一的 。
现在给定一个由小写英文字母构成的偶串\(S\),你需要求出\(f^{10^{100}}(S)\),并统计计算结果的第\(l\)个字符到第\(r\)个字符中,每个字母出现了多少次 。
其中,\(f^{10^{100}}(S)\)是指\(f(f(f(...f(S)...)))\),式子中共有\(10^{100}\)个\(f\) 。
Solution
打表找规律。从整个串来寻找规律看不出什么,反而是分别考虑两半的变化比较有效。
我们称\(T\)为\(S\)的"Border",当且仅当\(S\)作为\(T\)的循环串的前缀出现,且\(T\)长度最小。
现有输入串\(SS\),令\(S\)的"Border"为\(T\),则会发现:
\]
由于操作次数过多,只考虑前半部分的变化,就能回答所有询问:
\]
我们发现,从第三个串开始,每一个串\(i\),都是由串\(i-1\)+串\(i-2\)得来。姑且称它们为\(\text{fib}\)串。
特别地:若\(|S|-|T|\)整除\(|S|\),则变化为
\]
特判掉这种情况。
记\(len_i\)为第\(i\)个\(\text{fib}\)串的长度,\(g_{i,j}\)为第\(i\)个\(\text{fib}\)串中\(j\)字符出现了多少次。由于\(\text{fib}\)在第85项左右就已经超出了\(1e18\),因此我们可以暴力计算出这两个数组。
对答案差分,假设要求\(1...r\)中,每个字符的出现次数。
有结论是,只要有\(len_{x_1}+len_{x_2}+...+len_{x_k}=r\),且\(len_{x_1}>len_{x_2}>...>len_{x_k}\),则\(1...r\)这个字符串就可以用\(x_1,x_2,...,x_k\)这\(k\)个\(\text{fib}\)串首尾相接得到。
所以对于询问我们从大到小枚举\(\text{fib}\)串累加每个字符的答案。最后可能会剩余一定长度无法消去,但剩余的长度一定不超过\(|S|\)(在\(\text{fib}\)串中甚至没有组成一个元素\(S\)),且是\(S\)的一个前缀,额外计算上这些部分即可。
Code
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
const int N=200005;
int n,up,nex[N],type;
char str[N];
int pre[N][26];
ll l,r,cut,len[100],ans[26];
ll f[100][26];
void readData(){
scanf("%s%lld%lld",str+1,&l,&r);
n=strlen(str+1);
n>>=1;
for(int i=1;i<=n;i++){
for(int j=0;j<26;j++) pre[i][j]=pre[i-1][j];
pre[i][str[i]-'a']++;
}
}
void getNex(){
nex[1]=0;
for(int i=2,j;i<=n;i++){
j=nex[i-1];
while(j&&str[j+1]!=str[i]) j=nex[j];
nex[i]=(str[j+1]==str[i])?j+1:0;
}
}
void preWork(){
len[1]=n;
for(int i=1;i<=n;i++){
f[1][str[i]-'a']++;
f[2][str[i]-'a']++;
}
len[2]=n+cut;
for(int i=0;i<26;i++)
f[2][i]+=pre[cut][i];
for(int i=3;;i++){
for(int j=0;j<26;j++) f[i][j]=f[i-2][j]+f[i-1][j];
len[i]=len[i-2]+len[i-1];
if(len[i]>1e18){
up=i;
break;
}
}
}
void calc1(ll m,ll a){
if(m<=0) return;
ll t=m/cut;
for(int i=0;i<26;i++) ans[i]+=a*t*pre[cut][i];
t=m%cut;
for(int i=0;i<26;i++) ans[i]+=a*pre[t][i];
}
void calc2(ll m,ll a){
for(int i=up;i>=1;i--)
if(len[i]<=m){
m-=len[i];
for(int j=0;j<26;j++) ans[j]+=a*f[i][j];
}
for(int j=0;j<26;j++) ans[j]+=a*pre[m][j];
}
int main(){
readData();
getNex();
cut=n-nex[n];
if(n%cut==0){
calc1(r,1);
calc1(l-1,-1);
}
else{
preWork();
calc2(r,1);
calc2(l-1,-1);
}
for(int i=0;i<26;i++) printf("%lld ",ans[i]);
return 0;
}
【ARC077F】SS的更多相关文章
- 【ARC077F】SS kmp+打表找规律
Description 如果某个串可以由两个一样的串前后连接得到,我们就称之为"偶串".比如说"xyzxyz"和"aaaaaa"是偶串, ...
- 【arc077f】AtCoder Regular Contest 077 F - SS
题意 给你一个形如"SS"的串S,以及一个函数\(f(x)\),\(x\)是一个形如"SS"的字符串,\(f(x)\)也是一个形如"SS"的 ...
- 【arc077f】AtCoder Regular Contest 074 F - Lotus Leaves
题意 给定一个n*m的池塘,每个格子上可能有叶子. 从一个叶子出发,可以跳到相同行或相同列的叶子. 问至少去掉多少叶子,使得起点不能到达终点. \(n,m<=100\) 解法 很显然的最小割模型 ...
- 【转载】运维小技巧:使用ss命令代替 netstat
转自:https://www.91ri.org/12470.html ss是Socket Statistics的缩写. 顾名思义,ss命令可以用来获取socket统计信息,它可以显示和netstat类 ...
- 一步步实现ABAP后台导入EXCEL到数据库【1】
在SAP的应用当中,导入.导出EXCEL文件的情况是一个常见的需求,有时候用户需要将大量数据定期导入到SAP的数据库中.这种情况下,使用导入程序在前台导入可能要花费不少的时间,如果能安排导入程序为后台 ...
- 【Django】--Model字段
参考地址:http://www.cnblogs.com/wupeiqi/articles/6216618.html 所有字段 AutoField(Field) --int自增列,必须填入参数prima ...
- 通用js函数集锦<来源于网络> 【二】
通用js函数集锦<来源于网络> [二] 1.数组方法集2.cookie方法集3.url方法集4.正则表达式方法集5.字符串方法集6.加密方法集7.日期方法集8.浏览器检测方法集9.json ...
- 通用js函数集锦<来源于网络/自己> 【一】
通用js函数集锦<来源于网络/自己>[一] 1.返回一个全地址2.cookie3.验证用户浏览器是否是微信浏览器4.验证用户浏览器是否是微博内置浏览器5.query string6.验证用 ...
- 【五】将博客从jekyll迁移到了hexo
本系列有五篇:分别是 [一]Ubuntu14.04+Jekyll+Github Pages搭建静态博客:主要是安装方面 [二]jekyll 的使用 :主要是jekyll的配置 [三]Markdo ...
随机推荐
- EventBus的基本使用步骤
为什么要使用EventBus 当我们进行项目开发的时候,往往是需要应用程序的各组件间进行通信,比如在子线程中进行请求数据,当数据请求完毕后通过Handler或者是广播通知UI, 通常两个Activit ...
- Unity扩展编辑器二
Unity支持自行创建窗口,也支持自定义窗口布局,在Project视图中创建一个Editor文件夹,在文件夹中创建一条脚本 自定义窗口需要让脚本继承EditorWindow在设置MenuItem,此时 ...
- 深度学习中数据的augmentation
为了提高模型的泛化能力,同时也为了增大数据集,我们往往需要对数据进行augmentation,在这篇博客中,将总结一下可以对数据进行的augmentation. 1.颜色数据增强,对图像亮度.饱和度. ...
- 从Web抓取信息的几个常用方法
1.Response 对象有一个 status_code 属性,可以检查它是否等于requests.codes.ok. 2.raise_for_status()方法是一种很好的方式,确保程序在下载失败 ...
- VisionPro相机操作类
在网站上看到这个,保存下来,以后用到了,再看一下.谢谢原创的分享! #region 获得相机信息方法 /// <summary> /// 公有静态方法,查找单个相机.例如“Basler” ...
- Ubuntu16.04安装搜狗拼音输入法
为了让自己的电脑相对安全一些,我安装了ubuntu的物理机 因为要经常输入汉字,我就在unbuntu里面安装了搜狗输入法 1.在搜狗输入法官网下载Linux版本的安装包:https://pinyin. ...
- 入门向:南邮CTF_ReadAsm2_WP
题目链接:http://ctf.nuptzj.cn/challenges#ReadAsm2 我比较菜,所以把思路全部敲上来了. 题目很明确告诉我们,这道题考察阅读汇编代码的能力. 在对编译环境和调用约 ...
- Less 的用法
1. node.js node.js是一个前端的框架 自带一个包管理工具npm node.js 的安装 官网:http://nodejs.cn/ 在命令行检验是否安装成功 切换到项目目录,初始化了一个 ...
- linux下自己安装软件做成命令
安装nodejs,从官网下下来的是一个压缩包,解压下里面有可执行文件.教程上用ln -s [可执行文件的绝对路径] [/usr/local/bin/]建了一个软连接,这样就能直接无视路径,用命令行调用 ...
- 请教JDBC中的thin和OCI的区别\
请教JDBC中的thin和OCI的区别 https://zhidao.baidu.com/question/2267123737573204748.html