【2019 CCPC 秦皇岛】J - MUV LUV EXTRA
原题:


题意:
给你两个整数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的更多相关文章
- 2019CCPC秦皇岛 J MUV LUV EXTRA(KMP)
MUV LUV EXTRA Time Limit: 2000/1500 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)T ...
- HDU6740 2019CCPC秦皇岛赛区 J. MUV LUV EXTRA
题目:http://acm.hdu.edu.cn/showproblem.php?pid=6740思路:求小数部分后k位的真前后缀 倒着kmp就好 #include<bits/stdc++.h& ...
- 2019CCPC秦皇岛 K MUV LUV UNLIMITED(博弈)
MUV LUV UNLIMITED Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Othe ...
- 2019 ccpc 秦皇岛
D 如果1/n是有限小数,不停乘以10,一定在有限次之后成为一个整数. 10的质因子只有2和5,只要保证分母的质因子只有2和5即可 #include <iostream> #include ...
- 2019 ccpc秦皇岛
1006 (dfs) #include <bits/stdc++.h> using namespace std; const int inf = 0x3f3f3f3f; const dou ...
- 2019 CCPC wannfly winter camp Day 5
C - Division 思路:我们考虑到一点,从大往小取得顺序是不会有问题的,所以可以直接主席树,但是开不下空间,我们可以log分段求. #include<bits/stdc++.h> ...
- 2019 CCPC wannfly winter camp Day 8
E - Souls-like Game 直接线段树合并矩阵会被卡T掉,因为修改的复杂度比询问的复杂度多一个log,所以我们考虑优化修改. 修改的瓶颈在于打lazy的时候, 所以我们预处理出每个修改矩阵 ...
- 2019.ccpc女生赛-wfinal总结
2019ccpc女生赛离它结束有四天了,在这个期间我想了很多,想了想还是决定写这个总结.作为这个队伍唯一的一名大一队员,我很庆幸,能跟着两个学姐一起打比赛,计爱玲师姐,即将工作,张莹俐学姐.这估计都是 ...
- 2017 CCPC秦皇岛 M题 Safest Buildings
PUBG is a multiplayer online battle royale video game. In the game, up to one hundred players parach ...
随机推荐
- nrpe command
1. nrpe 连接问题: 报错:/usr/local/nagios/libexec/check_nrpe -H destip ; CHECK_NRPE: Error - Could no ...
- webdriver(处理select下拉框元素)
"""处理下拉框""" from selenium import webdriver from selenium.webdriver.com ...
- 【ARM-Linux开发】Linux下查看机器的CPU负载
负载(load)是Linux机器的一个重要指标,直观了反应了机器当前的状态.如果机器负载过高,那么对机器的操作将难以进行. Linux的负载高,主要是由于CPU使用.内存使用.IO消耗三部分构成.任意 ...
- JavaSE基础(十)--Java中的基本数据类型转换
Java中的基本数据类型转换 说基本数据类型转换之前,先了解下 Java 中的 8 种基本数据类型,以及它们的占内存的容量大小和表示的范围,如下图所示. 重新温故了下原始数据类型,现在来解释下它们之间 ...
- KMP算法最浅显理解——一看就明白
https://blog.csdn.net/starstar1992/article/details/54913261 说明 KMP算法看懂了觉得特别简单,思路很简单,看不懂之前,查各种资料,看的稀里 ...
- php分页思路
<?php class page{ public $nowPage=1; public $perPage=10; public $showPage=10; public $totalPage; ...
- linux fork进程请谨慎多个进程/线程共享一个 socket连接,会出现多个进程响应串联的情况。
昨天组内同学在使用php父子进程模式的时候遇到了一个比较诡异的问题 简单说来就是:因为fork,父子进程共享了一个redis连接.然后父子进程在发送了各自的redis请求分别获取到了对方的响应体. 复 ...
- linux下nginx搭建
1.准备 1-1.安装 make,zlib,gcc-c++,openssl yum -y install make zlib zlib-devel gcc-c++ libtool openssl o ...
- Creating mailbox file: 文件已存在
原来linux下添加用户后,会在系统里自动加一个邮箱(系统邮箱),路径是:/var/spool/mail/用户名.可以直接用命令#rm -rf /var/spool/mail/用户名 这样就可以再次添 ...
- 【leetcode】287. 寻找重复数
题目链接:传送门 题目描述: 给定一个数组 nums 包含 n + 1 个整数,每个整数在 1 到 n 之间,包括 1 和 n.现在假设数组中存在一个重复的数字,找到该重复的数字. 注意 不能修改数组 ...