【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]计算,然后统计到答案即可
代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 using namespace std; 7 #define LL long long 8 LL a,b; 9 char s[11000000]; 10 int c[11000000],n=0; 11 int nxt[11000000]; 12 LL ans; 13 void gtnxt(){ 14 int tmp=0; 15 nxt[1]=0; 16 for(int i=2;i<=n;++i){ 17 while(tmp&&c[tmp+1]!=c[i]) tmp=nxt[tmp]; 18 if(c[tmp+1]==c[i]) ++tmp; 19 nxt[i]=tmp; 20 /*if(nxt[i]){ 21 if(nxt[i]>=i-nxt[i]+1) ans=max(ans,a*i-b*(i-nxt[i])); 22 if(nxt[i]==i-nxt[i]) ans=max(ans,a*i-b*nxt[i]); 23 ans=max(ans,a*i*/ 24 if(nxt[i]) ans=max(ans,a*i-b*(i-nxt[i])); 25 } 26 } 27 int main(){ 28 //freopen("ddd.in","r",stdin); 29 while(scanf("%lld%lld",&a,&b)!=EOF){ 30 ans=-1e18,n=0; 31 scanf("%s",s); 32 for(int i=strlen(s)-1;i>=0;--i){ 33 if(s[i]=='.') break; 34 c[++n]=s[i]-'0'; 35 } 36 if(a-b>0) ans=(a-b)*n; 37 else ans=a-b; 38 gtnxt(); 39 cout<<ans<<endl; 40 /*for(int i=1;i<=n;++i) cout<<c[i]<<" "; 41 cout<<endl; 42 for(int i=1;i<=n;++i) cout<<nxt[i]<<" "; 43 cout<<endl;*/ 44 } 45 return 0; 46 }
原文地址:https://www.cnblogs.com/cdcq/p/11678950.html
- JavaScript 获取鼠标及元素在页面上的位置
- Spring cache简单使用guava cache
- SpringMVC参数校验(针对`@RequestBody`返回`400`)
- Java8学习(3)- Lambda 表达式
- Java8 in action(1) 通过行为参数化传递代码--lambda代替策略模式
- java中byte, iso-8859-1, UTF-8,乱码的根源
- 如何启动一个本地静态服务器
- Hello ReactJS
- git合并历史提交
- 常用连续型分布介绍及R语言实现
- banner自动生成工具,ascii文字展示
- 快速排序
- 2016.07 第2周 群问题分享
- 游戏开发 - Math对象相关知识讲解
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- IDEA上给文件添加姓名,日期,版本号
- matlab机器人工具箱安装与卸载
- 浅谈Linux下修改/设置环境变量JAVA_HOME的方法
- Linux服务器配置多个svn仓库流程详解
- linux服务器显卡崩溃解决方案
- LINUX查看进程的4种方法(小结)
- Linux下的多线程编程实例解析
- CentOS使用expect批量远程执行脚本和命令
- Centos8最小化部署安装OpenStack Ussuri的详细教程
- 详解Xshell 常见问题及相关配置
- linux安装部署ftp图片服务器的实现方法
- Centos7配置fastdfs和nginx分布式文件存储系统实现过程解析
- 解决Linux常用命令“ll”失效或命令未找到的问题
- 手把手教你在腾讯云上搭建hive3.1.2的方法
- centos6超20TB磁盘的分区格式化的示例代码