EOJ Monthly 2018.12 F. 日落轨迹

题解: 对于任何一个串的前x字符内的本质不同子串 我们可以直接在SAM树上得到 然后我们考虑循环串的性质 (设循环节长度为l ) 则大于2*l的位置为等差数列 即每增加一个字符则增加l个本质不同的子串 所以对于2*l我们在后缀树上处理处理 对于x>2*l我们 通过等差求得

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#include <queue>
#include <cmath>
#include <set>
#include <map>
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define link(x) for(edge *j=h[x];j;j=j->next)
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,r,l) for(int i=r;i>=l;i--)
const int MAXN=4e5+10;
const double eps=1e-8;
const int mod1=1e9+7;
const int mod2=1e9+9;
#define ll long long
using namespace std;
struct edge{int t,v;edge*next;}e[MAXN<<1],*h[MAXN],*o=e;
void add(int x,int y,int vul){o->t=y;o->v=vul;o->next=h[x];h[x]=o++;}
ll read(){
    ll x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch==‘-‘)f=-1;ch=getchar();}
    while(isdigit(ch))x=x*10+ch-‘0‘,ch=getchar();
    return x*f;
}
char str[MAXN];
ll ans[MAXN],sum;
int dis[MAXN],fa[MAXN],ch[MAXN][26];
int cnt,cur,rt;
ll ksm(ll a,ll b,ll c){
    ll ans=1;
    while(b){
	if(b&1)ans=ans*a%c;
	a=a*a%c;b=b>>1;
    }
    return ans;
}
int nxt[MAXN];
void Next(char str[],int len){
    int i=0,j=-1;nxt[0]=-1;
    while(i<len){
	if(j==-1||str[i]==str[j])nxt[++i]=++j;
	else j=nxt[j];
    }
}
void built(int x){
    int last=cur;cur=++cnt;dis[cur]=dis[last]+1;int p=last;
    for(;p&&!ch[p][x];p=fa[p])ch[p][x]=cur;
    if(!p)fa[cur]=rt,sum+=dis[cur];
    else{
	int q=ch[p][x];
	if(dis[q]==dis[p]+1)fa[cur]=q,sum+=dis[cur]-dis[fa[cur]];
	else{
	    int nt=++cnt;dis[nt]=dis[p]+1;
	    memcpy(ch[nt],ch[q],sizeof(ch[q]));
	    fa[nt]=fa[q];sum+=dis[nt]-dis[fa[nt]];
	    sum-=dis[q]-dis[fa[q]];fa[q]=fa[cur]=nt;
	    sum+=dis[q]-dis[fa[q]];sum+=dis[cur]-dis[fa[cur]];
	    for(;ch[p][x]==q;p=fa[p])ch[p][x]=nt;
	}
    }
}

int main(){
    int n=read(),q=read();
    inc(i,0,n-1)scanf(" %c",&str[i]),str[i+n]=str[i];
    Next(str,n);
    int t1=nxt[n];
    int m=n-t1;
    if(n%m!=0)m=n;
    cnt=rt=cur=1;
    inc(i,0,2*n-1)built(str[i]-‘a‘),ans[i]=sum;
    while(q--){
	int t=read();
	if(t<=2*m)printf("%lld\n",ans[t-1]);
	else{
	    t-=2*m;ll ans1=1ll*t*m+ans[2*m-1];
	    printf("%lld\n",ans1);
	}
    }
    return 0;
}

 

F. 日落轨迹

单测试点时限: 2.5 秒

内存限制: 512 MB

“我喜欢看日落,我们一起看日落吧。”
“可是得等等。”
“等什么?”
“等太阳落山。”

你的星球只有房子那么大,只要你愿意,挪动几步椅子就可以随时看到你喜欢的夕阳晚景了。

但你和他不同,没有小狐狸的陪伴,身旁只有一台呆板的摄像机忠实地记录着日落的轨迹。

日落的轨迹总是如此的相似,以至于在你的摄像机中每一次日落的场景都毫无差别。

可你不甘于单调,希望在重复中找到不同。你通过截取很多很多不同的日落片段,来表现日落的变化多姿。

你找出了摄像机的视频,发现它的编码都是由小写字母构成的。一段日落场景则是由一个全部是小写字母的字符串 S 构成;摄像机中的场景,就是字符串 S 被复制很多很多份后组成的大字符串 SSSS?。

你所谓的不同日落片段的个数,就是寻找大字符串 SSSS? 中前 x 位中有所少个本质不同的子串。

输入

第一行输入两个整数 n,q (1≤n,q≤105),表示字符串 S 的长度和询问的个数。

第二行输入一个长度为 n 的由小写字母组成的字符串 S。

接下来的 q 行,每行包含一个整数 x (1≤x≤109),表示询问大字符串 SSSS? 的前 x 中有多少个本质不同的子串。

输出

输出包含 q 行,第 i 行一个整数,代表第 i 个询问的答案。

样例

input

4 5
abaa
2
4
5
10
123

output

3
8
11
31
483

原文地址:https://www.cnblogs.com/wang9897/p/10086405.html

时间: 2024-10-11 14:25:46

EOJ Monthly 2018.12 F. 日落轨迹的相关文章

EOJ Monthly 2018.1 F 最小OR路径

题目链接 Description 给定一个有 \(n\) 个点和 \(m\) 条边的无向图,其中每一条边 \(e_i\) 都有一个权值记为 \(w_i\) . 对于给出的两个点 \(a\) 和 \(b\) ,求一条 \(a\) 到 \(b\) 的路径,使得路径上的边权的 \(OR\)(位或)和最小,输出这个值.(也就是说,如果将路径看做边的集合 \(\{e_1,e_2,-,e_k\}\),那么这条路径的代价为 \(w_1\ OR\ w_2\ OR\ -\ OR\ w_k\),现在求一条路径使得其

【EOJ Monthly 2018.2 (Good bye 2017)】

23333333333333333 由于情人节要回家,所以就先只放代码了. 此题是与我胖虎过不去. [E. 出老千的 xjj] #include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int maxn=3000000; #define ll long long int

EOJ Monthly 2018.2

A. 坑爹的售票机 题意 用\(1,5,10,25,50,100\)的纸币买\(n\)张单价为\(p\)的船票,且一次性最多买\(k\)张,求钱数恰好时最少需要多少张纸币. Hard: \(n,k,p\leq 10^9\) 思路 Easy: dp Hard: dp + 瞎搞 当钱数过大或者张数过多时,(由直觉)其中的大部分都是遵循一定的规律来取的,只有剩余的一小部分需要dp. Code Easy #include <bits/stdc++.h> #define F(i, a, b) for (

[EOJ Monthly 2018.10][C. 痛苦的 01 矩阵]

题目链接:C. 痛苦的 01 矩阵 题目大意:原题说的很清楚了,不需要简化_(:з」∠)_ 题解:设\(r_i\)为第\(i\)行中0的个数,\(c_j\)为第\(j\)列中0的个数,\(f_{i,j}\)代表对应格子是否为0,则有\(cost(i,j)=r_i+c_j-f_{i,j}\),\((cost(i,j))^2=r_i^2+c_j^2+f_{i,j}+2r_ic_j-2f_{i,j}(r_i+c_j)\) $$\sum_{i=1}^n \sum_{j=1}^n \left( cost(

ZOJ 4009 And Another Data Structure Problem(ZOJ Monthly, March 2018 Problem F,发现循环节 + 线段树)

题目链接  ZOJ Monthly, March 2018 Problem F 题意很明确 这个模数很奇妙,在$[0, mod)$的所有数满足任意一个数立方$48$次对$mod$取模之后会回到本身. 所以开$48$棵线段树,和一个永久标记.当对某个区间操作时对这个区间加一层永久标记. 即当前我要查找的第$x$层,实际找的是第$up[i] + x$层. 时间复杂度$O(48nlogn)$ #include <bits/stdc++.h> using namespace std; #define

2018.12.1 Test

目录 2018.12.1 Test A 串string(思路) B 变量variable(最小割ISAP) C 取石子stone(思路 博弈) 考试代码 B C 2018.12.1 Test 题目为2018.1.2雅礼集训. 时间:3.5h 期望得分:100+30+10 实际得分:100(0)+0+10 A 串string(思路) 如果一个串不是回文串,答案是1(我竟然漏了QAQ). 否则,除了以下三种情况无解外,都能两次消掉: aaaaa aabaa ababa 判一下就OK了. #inclu

web前端 2018/12/06

一.web前端2018/12/06单词: password   charset   submit   reset   checkbox  placeholder  texteara   radio  method file dorecation 二.web前端常用标签: 行内标签:b,a,strong,i,em...... 行内转块标签:display:block: 块元素标签:div,p,h1~h6, ul/ol(项下只能放li标签),  li(父级只能是ul 或者li)...... 块元素标

2018.12筑基

2018.12.11 名言佳句:1 理论表述:1 核心词汇:1 申论感悟:1 原文地址:https://www.cnblogs.com/earnestron15/p/10100117.html

【谜客帝国】第144届猫De梦年度收官谜会(2018.12.30)

[谜客帝国]第144届猫De梦年度收官谜会(2018.12.30) 主持:瓷  计分:小白 1.愿人生,有幸一起同行(3字中药名)天南星/猫De梦 2.分手不成聚难卜(4字谜会吐槽语)没离合谜/猫De梦 3.老做加法没益处(5字劝架结果描述)总算和好了/猫De梦 4.以前有给回扣(3字交通名词)往返点/猫De梦 5.几经流年终杳远(2字已故艺术家)朱旭/猫De梦 6.看来只好换工作了(3字口语二)顾不得,不更事/猫De梦 7.相较之下,这算挑到好的啦(4字考试答案判断语,卷帘)选正比对/猫De梦