原题:

题意:

给你两个整数a和b,再给你一个正小数,整数部分忽略不计,只考虑小数部分的循环节,对于所有可能的循环节,令其长度为l,在小数部分循环出现的长度为p,最后一个循环节允许不完整,但是缺少的部分不计入循环长度

问你a*p-b*l的最小值是多少

考虑的循环节必须至少在小数部分中出现一次,小数部分的前缀可以不属于循环部分

这题也是一眼很棘手,和后缀数组和后缀自动机似乎都有相似之处

但是实际做法是kmp

翻转原串是关键思路,这样保证了能把原串前缀的不是循环部分的部分忽略掉,从而方便地利用next数组的性质

把小数部分串反过来,那么这个串的前缀就一定是循环部分

因为最后循环节允许不完整,所以考虑把一个循环节分成AB两部分,其中B是最后一个循环节缺的部分

考虑next数组的性质:next[i]表示子串[1,i]最长的前后缀长度,使得此长度的前后缀相等

那么对于ACA形式的串,其中A指最长的相同前后缀,把C接到A后边就可以变成ACA(C)的循环形式,前后缀有相交情况时同理

对于循环部分[1,i],出现长度就是i,出现长度固定,只需求出此时长度最小的循环节

由next的性质,保证[1,i-next[i]]是最小的循环节

可以反证,考虑ABABABABA,如果它被i-nxt[i]和next[i]+1划分为ABA BAB ABA,即认为[1,6]和[4,9]是相同的前后缀,且有多余的循环节被统计到了[1,i-nxt[i]]和[nxt[i]+1,i]里

那么此时可以从[1,i-nxt[i]]和[nxt[i],i]中各拿出一个循环节放到中间,易证此时仍然符合next[i]的性质,即之前求出的next[i]是错误的

所以得证,[1,i-next[i]]一定是最小的循环节

那么把小数部分倒过来,从左到右扫一遍,每次根据next[i]计算,然后统计到答案即可

代码:

 #include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
#define LL long long
LL a,b;
char s[];
int c[],n=;
int nxt[];
LL ans;
void gtnxt(){
int tmp=;
nxt[]=;
for(int i=;i<=n;++i){
while(tmp&&c[tmp+]!=c[i]) tmp=nxt[tmp];
if(c[tmp+]==c[i]) ++tmp;
nxt[i]=tmp;
/*if(nxt[i]){
if(nxt[i]>=i-nxt[i]+1) ans=max(ans,a*i-b*(i-nxt[i]));
if(nxt[i]==i-nxt[i]) ans=max(ans,a*i-b*nxt[i]);
ans=max(ans,a*i*/
if(nxt[i]) ans=max(ans,a*i-b*(i-nxt[i]));
}
}
int main(){
//freopen("ddd.in","r",stdin);
while(scanf("%lld%lld",&a,&b)!=EOF){
ans=-1e18,n=;
scanf("%s",s);
for(int i=strlen(s)-;i>=;--i){
if(s[i]=='.') break;
c[++n]=s[i]-'';
}
if(a-b>) ans=(a-b)*n;
else ans=a-b;
gtnxt();
cout<<ans<<endl;
/*for(int i=1;i<=n;++i) cout<<c[i]<<" ";
cout<<endl;
for(int i=1;i<=n;++i) cout<<nxt[i]<<" ";
cout<<endl;*/
}
return ;
}

【2019 CCPC 秦皇岛】J - MUV LUV EXTRA的更多相关文章

  1. 2019CCPC秦皇岛 J MUV LUV EXTRA(KMP)

    MUV LUV EXTRA Time Limit: 2000/1500 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)T ...

  2. HDU6740 2019CCPC秦皇岛赛区 J. MUV LUV EXTRA

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=6740思路:求小数部分后k位的真前后缀 倒着kmp就好 #include<bits/stdc++.h& ...

  3. 2019CCPC秦皇岛 K MUV LUV UNLIMITED(博弈)

    MUV LUV UNLIMITED Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Othe ...

  4. 2019 ccpc 秦皇岛

    D 如果1/n是有限小数,不停乘以10,一定在有限次之后成为一个整数. 10的质因子只有2和5,只要保证分母的质因子只有2和5即可 #include <iostream> #include ...

  5. 2019 ccpc秦皇岛

    1006 (dfs) #include <bits/stdc++.h> using namespace std; const int inf = 0x3f3f3f3f; const dou ...

  6. 2019 CCPC wannfly winter camp Day 5

    C - Division 思路:我们考虑到一点,从大往小取得顺序是不会有问题的,所以可以直接主席树,但是开不下空间,我们可以log分段求. #include<bits/stdc++.h> ...

  7. 2019 CCPC wannfly winter camp Day 8

    E - Souls-like Game 直接线段树合并矩阵会被卡T掉,因为修改的复杂度比询问的复杂度多一个log,所以我们考虑优化修改. 修改的瓶颈在于打lazy的时候, 所以我们预处理出每个修改矩阵 ...

  8. 2019.ccpc女生赛-wfinal总结

    2019ccpc女生赛离它结束有四天了,在这个期间我想了很多,想了想还是决定写这个总结.作为这个队伍唯一的一名大一队员,我很庆幸,能跟着两个学姐一起打比赛,计爱玲师姐,即将工作,张莹俐学姐.这估计都是 ...

  9. 2017 CCPC秦皇岛 M题 Safest Buildings

    PUBG is a multiplayer online battle royale video game. In the game, up to one hundred players parach ...

随机推荐

  1. nrpe command

    1. nrpe 连接问题: 报错:/usr/local/nagios/libexec/check_nrpe  -H  destip   ;   CHECK_NRPE: Error - Could no ...

  2. webdriver(处理select下拉框元素)

    """处理下拉框""" from selenium import webdriver from selenium.webdriver.com ...

  3. 【ARM-Linux开发】Linux下查看机器的CPU负载

    负载(load)是Linux机器的一个重要指标,直观了反应了机器当前的状态.如果机器负载过高,那么对机器的操作将难以进行. Linux的负载高,主要是由于CPU使用.内存使用.IO消耗三部分构成.任意 ...

  4. JavaSE基础(十)--Java中的基本数据类型转换

    Java中的基本数据类型转换 说基本数据类型转换之前,先了解下 Java 中的 8 种基本数据类型,以及它们的占内存的容量大小和表示的范围,如下图所示. 重新温故了下原始数据类型,现在来解释下它们之间 ...

  5. KMP算法最浅显理解——一看就明白

    https://blog.csdn.net/starstar1992/article/details/54913261 说明 KMP算法看懂了觉得特别简单,思路很简单,看不懂之前,查各种资料,看的稀里 ...

  6. php分页思路

    <?php class page{ public $nowPage=1; public $perPage=10; public $showPage=10; public $totalPage; ...

  7. linux fork进程请谨慎多个进程/线程共享一个 socket连接,会出现多个进程响应串联的情况。

    昨天组内同学在使用php父子进程模式的时候遇到了一个比较诡异的问题 简单说来就是:因为fork,父子进程共享了一个redis连接.然后父子进程在发送了各自的redis请求分别获取到了对方的响应体. 复 ...

  8. linux下nginx搭建

    1.准备 1-1.安装 make,zlib,gcc-c++,openssl yum -y install make zlib zlib-devel gcc-c++ libtool  openssl o ...

  9. Creating mailbox file: 文件已存在

    原来linux下添加用户后,会在系统里自动加一个邮箱(系统邮箱),路径是:/var/spool/mail/用户名.可以直接用命令#rm -rf /var/spool/mail/用户名 这样就可以再次添 ...

  10. 【leetcode】287. 寻找重复数

    题目链接:传送门 题目描述: 给定一个数组 nums 包含 n + 1 个整数,每个整数在 1 到 n 之间,包括 1 和 n.现在假设数组中存在一个重复的数字,找到该重复的数字. 注意 不能修改数组 ...