Description

  

  给你一个长度不超过100的字符串。一共进行\(N\)次操作,第\(i\)次操作是将当前字符串复制一份接到后面,并将新的一份循环移位\(k_i\)(\(1 \le k_i \le 100\))次。给出\(M\)(\(1 \le M \le 100000\))个询问,每次询问所有操作完成之后,\([l,r]\)中,某个字母出现了多少次。其中\(1 \le l \le r \le 10^{18}\)。

  

  

  

Solution

  

   我开场就写了2个小时的暴力分治,并惊喜地发现单个询问可以秒出。结果一组询问需要0.01s,拿到了40分的好成绩。

  

   首先\(N\)只有约前60项是有意义的,因此总操作数大约是60次。

  

   这种字符串变换题目要重点观察变换前和变换后是否有一大块一大块是相等的。比如某次操作前,字符串是\(S\),\(A\)和\(B\)是\(S\)的两块(即\(S=AB\))其中B的长度恰好是这次操作的偏移值。那么操作完之后,字符串的变化如下:

\[AB\rightarrow AB\;BA
\]

   既然只有60次操作,而每次操作的\(B\)的长度不超过100,我们完全可以算出每次操作的\(B\)串。即枚举每个字符,反向模拟这个字符是怎么从原串变换来的,即可在一个\(\log\)的时间确定每个字符是什么。

  

   将询问查分,则我们要求\([1,n]\)中有多少个\(c\)字符。

  

   考虑从最后一次操作开始递归向前计算(其实应该是:最早的一次操作,满足操作后串长不小于\(n\))。

  

   如果\(n\)落在左边的\(AB\)内:那么直接递归前一次操作,返回其答案。

  

   如果\(n\)落在右边的\(B\)内:左半边\(AB\)的答案显然,就是原串中这个字符的数量乘上左半边有多少个原串。对于右边部分,我们预处理出每次操作中\(B\)的字母前缀和,\(O(1)\)可询问\(B\)前缀字母数量。两者加起来就是答案。

  

   如果\(n\)落在右边的\(A\)内:\(ABB\)的答案可以用上一个情况的思路直接算,而最右边的\(A\)的答案,其实就是最左边的\(A\)的对应位置的答案。和第一种情况一样,我们递归前一次操作即可知道这部分的答案。

  

   我们发现总分治递归层数不会超过有效操作次数。因此这题可以在\(\mathcal O(M\log 10^{18})\)内解决。

  

  

  

Code

  

#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
namespace IO{
const int S=20000005;
char buffer[S];
int pos;
void Load(){
pos=0;
fread(buffer,1,S,stdin);
}
char getChar(){
char res=buffer[pos++];
if(pos>=S)
Load();
return res;
}
ll getLong(){
ll x=0,f=1;
char c=getChar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getChar();}
while('0'<=c&&c<='9'){x=x*10+c-'0';c=getChar();}
return x*f;
}
int getStr(char *str){
int len=0;
for(char c=getChar();'a'<=c&&c<='z';c=getChar())
str[len++]=c;
return len;
}
}
using IO::getLong;
using IO::getStr;
const int N=110,B=70,C=26;
const ll UP=2e18;
char str[N];
int slen;
int n,m,off[100005];
int pre[N][C],f[B][N][C];
void readData(){
slen=IO::getStr(str+1);
n=getLong(); m=getLong();
for(int i=1;i<=n;i++)
off[i]=getLong();
}
inline ll get_len(int bit){
return 1ll*slen*(1ll<<bit);
}
char get_char(int bit,ll x){
if(bit==0)
return str[x];
ll mid=get_len(bit-1);
if(x<=mid)
return get_char(bit-1,x);
ll cut=mid+off[bit];
if(x<=cut)
return get_char(bit-1,mid-(cut-x));
else
return get_char(bit-1,x-cut);
}
void precount(){
for(int i=1;i<=slen;i++){
for(int j=0;j<26;j++)
pre[i][j]=pre[i-1][j];
pre[i][str[i]-'a']++;
}
for(int i=1;get_len(i)<UP;i++){
ll mid=get_len(i-1);
off[i]%=mid;
for(int j=1;j<=off[i];j++){
for(int k=0;k<26;k++)
f[i][j][k]+=f[i][j-1][k];
char c=get_char(i-1,mid-off[i]+j);
f[i][j][c-'a']++;
}
}
}
ll solve(int bit,ll n,int c){
if(bit==0)
return pre[n][c];
ll mid=get_len(bit-1),cut=mid+off[bit];
if(n<=mid)
return solve(bit-1,n,c);
if(n<=cut)
return 1ll*pre[slen][c]*(1ll<<(bit-1))+f[bit][n-mid][c];
else
return 1ll*pre[slen][c]*(1ll<<(bit-1))+f[bit][cut-mid][c]+solve(bit-1,n-cut,c);
}
ll calc(ll n,char c){
if(!n)
return 0;
int bit;
for(bit=0;get_len(bit)<n;bit++);
return solve(bit,n,c-'a');
}
void answerQuery(){
ll l,r;
char c[2];
for(int i=1;i<=m;i++){
l=getLong(); r=getLong(); getStr(c);
printf("%lld\n",calc(r,c[0])-calc(l-1,c[0]));
}
}
int main(){
IO::Load();
readData();
precount();
answerQuery();
return 0;
}

CJB的大作的更多相关文章

  1. NOIp2018模拟赛三十五

    两道大数据结构把我砸懵 成绩:未提交 Orz xfz两道正解 A:[BZOJ4049][CREC2014B]mountainous landscape B:CJB的大作(CF改编题)

  2. 转载部长一篇大作:常用排序算法之JavaScript实现

    转载部长一篇大作:常用排序算法之JavaScript实现 注:本文是转载实验室同门王部长的大作,找实习找工作在即,本文颇有用处!原文出处:http://www.cnblogs.com/ywang172 ...

  3. cjb

    输入216.194.70.6 ,进入到是cjb.net的主页,并不是shell.cjb.net ,进入主页后点击shell,就进不去了 分析:shell.cjb.net被DNS污染了 解法:hosts ...

  4. Bishop的大作《模式识别与机器学习》Ready to read!

    久仰Bishop的大作“Pattern Recognition and Machine Learning”已久,在我的硬盘里已经驻扎一年有余,怎奈惧其页数浩瀚,始终未敢入手.近日看文献,屡屡引用之.不 ...

  5. 当今游戏大作share的特性大盘点

    极品游戏制作时的考虑要素大盘点 不知不觉入坑Steam已近4年,虽然说Steam的毒性让很多人走向一条不归路,但是想我这样即使"中毒"还是很快乐很感恩的.那么本期文章就谈谈我对其中 ...

  6. 深入Guerrilla Games解密次世代开山大作《杀戮地带暗影坠落》(The technology of Killzone Shadow Fall)

    文章摘要:这几天终于有时间,把全文翻译完了,自己感觉不是太满意,不过大家能看懂就好,就当一个学习的机会.整篇文章通过SONY第一方游戏工作室Guerrilla Games主创的语录,为我们展现了次世代 ...

  7. 关于Delphi中的字符串的浅析(瓢虫大作,里面有内存错误的举例)

    关于Delphi中的字符串的浅析 只是浅浅的解析下,让大家可以快速的理解字符串. 其中的所有代码均在Delphi7下测试通过. Delphi 4,5,6,7中有字符串类型包括了: 短字符串(Short ...

  8. 採訪The Molasses Flood:BioShock Infinite 游戏之后又一大作

    Xsolla有幸与Flame in the Flood游戏的开发人员之中的一个-----Forrest Dowling进行了採訪,Flame in the Flood这款非常棒的游戏在Kickstar ...

  9. 5月,专用程序猿的经典大作——APUE

    五一小长假刚刚过去,收回我们游走的心.開始你们的读书旅程吧! 本期特别推荐 经典UNIX著作最新版. 20多年来,这本书帮助几代程序猿写出强大.高性能.可靠的代码. 第3版依据当今主流系统进行更新,更 ...

随机推荐

  1. CentOS 建立本地yum源服务器

    安装CentOS系统,配置系统的网络环境 配置静态IP vi /etc/sysconfig/network-scripts/ifcfg-eth0 DEVICE=eth0 TYPE=Ethernet O ...

  2. Maven的继承与聚合——多模块开发

    一:Maven多模块项目,适用于一些比较大的项目,通过合理的模块拆分,实现代码的复用,便于维护和管理.尤其是一些开源框架,也是采用多模块的方式,提供插件集成,用户可以根据需要配置指定的模块. 二:继承 ...

  3. FakeID签名漏洞分析及利用(一)

    作者:申迪   转载请注明出处: http://blogs.360.cn/360mobile BlueBox于7月30日宣布安卓从2010年以来一直存在一个apk签名问题[1],并且会在今年Black ...

  4. Ueditor使用笔记

            富文本编辑器在javaweb项目中还是比较常见的,如:ckeditor.kindeditor.ueditor等.今天主要叙述的对象为ueditor,它属于百度的.闲话不多说,下面开始介 ...

  5. Octocat,看着喜欢就都下载下来了

    看见github的octocat很喜欢,就用c#写了个程序统统download了,附上一个比较高效的下载程序,以及文末的图片压缩包. 用到了Jumony解析网页. HttpClient client ...

  6. 记一次Spring的aop代理Mybatis的DAO所遇到的问题

    由来 项目中需要实现某个订单的状态改变后然后推送给第三方的功能,由于更改状态的项目和推送的项目不是同一个项目,所以为了不改变原项目的代码,我们考虑用spring的aop来实现. 项目用的是spring ...

  7. android studio 下载 sdk 失败

    android studio 打开项目出现以下错误时,点击去安装,会提示"All packages are not available for download" 错误. 解决办法 ...

  8. 如何设计一个异步Web服务——接口部分

    需求比较简单,提供一个异步Web服务供使用者调用.比如说,某应用程序需要批量地给图片加lomo效果.由于加lomo效果这个操作非常消耗CPU资源,所以我们需要把这个加lomo效果的程序逻辑放到一台单独 ...

  9. Nginx浅析

    Nginx浅析 Nginx是什么 总的来说,Nginx其实就是一个和apache类似的服务器软件. Nginx是一款轻量级的Web服务器/反向代理服务器以及电子邮件代理服务器,并在一个BSD-like ...

  10. OD之修改文件标题(一)

    OD是逆向工程中的一个重要工具,逆向工程调试说明具体请参考:百度百科,OD介绍,当然就我了解而言,俗话就是破解软件,市面上的什么破解版,精简版啥的基本都是通过这种技术的,但是这并不能一概而论说逆向工程 ...