题意:对一个等差数列$a_i=A+Bi(0\leq i\leq n-1)$和非负整数$x$,把$a_i$的$10^x$位拿出来可以写成一个字符集为$0\cdots9$的字符串,现在给定这个字符串$d_{0\cdots n-1}$,求最小的$A$,或输出无解

如果$x\gt0$,那么有可能产生进位,所以$d_{i+1}-d_i$的取值最多能有$2$种,如果只有$1$种,显然$d_0$就是答案

如果有两种,这两种取值在$\bmod10$意义下必须相差$1$,较小那个($9\lt0$)就是$B$的$x-1$位

先扫一遍,用$B$的$x$位把$d_i$的$x$位向高位的进位复原,得到$d'_i$,现在条件变为$\left\lfloor\frac{a_i}{10^x}\right\rfloor=d'_i$,也可以写成$d'_i\cdot10^x\leq a_i\lt(d'_i+1)\cdot10^x$

我们已经知道了$d_i'$,现在要找到符合以上不等式的$a_i$并使得$a_0$最小,因为$x$越大限制越宽松,同时最小的$a_0$越大,所以考虑从小到大枚举$x$并判断是否能满足条件

实际上我们要找的是一条直线,它必须经过每条端点为$(i,d'_i\cdot10^x),(i,(d'_i+1)\cdot10^x)$的线段,两两枚举$d'_i$和$d'_j+1$,求出斜率的范围,然后不停增大$x$直到这个范围包含整数为止

虽然$n=10^4$,但因为atcoder评测机实在太快了,所以是能过的

以下是更快的方法(我没写==)

横纵坐标范围为$O(n)$的任意整点点集的凸包的大小为$O(n^{\frac23})$,证明如下(来自zjt)

先考虑求左下凸壳的大小,其他方向是一样的,这个凸壳的每条边对应的向量互相叉积$\gt0$,且所有向量的$x$之和和$y$之和都是$O(n)$级别的($x,y\geq0$)

对问题进行弱化:所有向量的$x+y$之和是$O(n)$的,并且我们不要求向量只需不相等

如果每个$(i,j)$都满足$i,j\leq m$,那么$\sum\limits_{i\leq m}\sum\limits_{j\leq m}i+j=O(n)$,即$m=O(n^{\frac13})$,所以不同的向量数只有$O(n^{\frac23})$个

所以凸包的大小也是$O(n^{\frac23})$,因为对问题做了三次弱化,所以实际上凸包上的点还会少很多

先求出所有$(i,d'_i\cdot10^x)$的上凸壳和$(i,(d'_i+1)\cdot10^x)$的下凸壳,由上述定理,在两个凸壳上枚举点对的时间复杂度为$O(n^{\frac43})$

最快当然还是在上凸壳枚举点,在下凸壳上的对应点只会单调地移动,时间复杂度$O(n)$

注意涉及到斜率作差时,如果坐标范围为$M$,$eps$一般要开到$\frac1{M^2}$,这个随便找一个极端情况就知道了

#include<stdio.h>
#include<string.h>
#include<set>
#include<math.h>
using namespace std;
typedef double du;
const du eps=1e-9;
char s[10010];
int a[10010];
set<int>d;
int go(int x,int y){return(y-x+10)%10;}
int main(){
	int n,i,j,dd,pw,B,res;
	du mn,mx;
	scanf("%s",s);
	n=strlen(s);
	for(i=0;i<n-1;i++)d.insert(go(s[i],s[i+1]));
	if(d.size()<2u){
		putchar(s[0]);
		return 0;
	}
	#define wa {puts("-1");return 0;}
	#define s1 *d.begin()
	#define s2 *d.rbegin()
	if(d.size()>2u||(go(s1,s2)!=1&&go(s2,s1)!=1))wa
	dd=s2==s1+1?s1:s2;
	a[0]=s[0]-'0';
	for(i=1;i<n;i++){
		a[i]=a[i-1]+dd;
		if(a[i]%10!=s[i]-'0')a[i]++;
		if(a[i]%10!=s[i]-'0')wa
	}
	mn=0;
	mx=1e9;
	for(i=0;i<n-1;i++){
		for(j=i+1;j<n;j++){
			mn=max(mn,(a[j]-(a[i]+1)+eps)/(du)(j-i));
			mx=min(mx,((a[j]+1)-a[i]-eps)/(du)(j-i));
		}
	}
	if(mn>mx)wa
	for(pw=1;ceil(mn*pw)>floor(mx*pw);pw*=10);
	B=floor(mx*pw);
	res=0;
	for(i=0;i<n;i++)res=max(res,a[i]*pw-B*i);
	printf("%d",res);
}

[ARC055D]隠された等差数列的更多相关文章

  1. 等差数列(bzoj 3357)

    Description     约翰发现奶牛经常排成等差数列的号码.他看到五头牛排成这样的序号:"1,4,3,5,7" 很容易看出"1,3,5,7"是等差数列. ...

  2. 3357: [Usaco2004]等差数列

    3357: [Usaco2004]等差数列 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 321  Solved: 153[Submit][Statu ...

  3. Find Missing Term in Arithmetic Progression 等差数列缺失项

    查找等差数列中的缺失项. e.g.Input: arr[] = {2, 4, 8, 10, 12, 14} Output: 6 Input: arr[] = {1, 6, 11, 16, 21, 31 ...

  4. ASP.NET MVCでResponse Headerのサーバーバージョンをどうやって隠しますか?

    本来是发布在客户的Wiki上的,所以用日语写. ---------------------------------------------------------------------------- ...

  5. n个整数中,找出尽可能多的数使他们组成一个等差数列,求最长等差数列的长度

    例子:  3,8,4,5,6,2          返回值应该为 :5 这是昨天做的一道优酷土豆的编程题,和leetcode中的128/ Longest Consecutive Sequence 有点 ...

  6. 洛谷 P1147 连续自然数和 Label:等差数列

    题目描述 对一个给定的自然数M,求出所有的连续的自然数段,这些连续的自然数段中的全部数之和为M. 例子:1998+1999+2000+2001+2002 = 10000,所以从1998到2002的一个 ...

  7. TYVJ P1091 等差数列 Label:dp

    背景 广东汕头聿怀初中 Train#3 Problem 3 描述 等差数列的定义是一个数列S,它满足了(S[i]-S[i-1]) = d (i>1).显然的一个单独的数字或者两个数字也可以形成一 ...

  8. 洛谷P1214 [USACO1.4]等差数列 Arithmetic Progressions

    P1214 [USACO1.4]等差数列 Arithmetic Progressions• o 156通过o 463提交• 题目提供者该用户不存在• 标签USACO• 难度普及+/提高 提交 讨论 题 ...

  9. 51nod1055 最长等差数列

    完全一脸懵逼!.dp[i][j]表示i,j为相邻的两项的最大值.两个指针两边扫的思想好劲啊这个!%%% #include<cstdio> #include<cstring> # ...

随机推荐

  1. centOS7 vsftp ExecStart=/usr/sbin/vsftpd /etc/vsftpd/vsftpd.conf (code=exited, status=0/SUCCESS) 启动失败问题?

    [root@localhost c]# systemctl status vsftpd.service ● vsftpd.service - Vsftpd ftp daemon Loaded: loa ...

  2. dlmalloc(一)【转】

    转自:http://blog.csdn.net/ycnian/article/details/12971863 我们写过很多C程序了,经常会分配内存.记得刚学C语言时老师说过,可以向两个地方申请内存: ...

  3. UBIFS学习笔记

    在做项目的时候,发现flash芯片有异常现象,经过打印分析,发现是UBIFS方面设置有一些问题,经过查阅一部分资料,最终得到问题的答案. 在解决问题的过程中,发现打印信息比较重要,但网上并没有直接的相 ...

  4. 72.Edit Distance---dp

    题目链接:https://leetcode.com/problems/edit-distance/description/ 题目大意:找出两个字符串之间的编辑距离(每次变化都只消耗一步). 法一(借鉴 ...

  5. linux系统性能排查命令

    [top] 命令可以动态查看当前系统的资源情况,以及占用资源的命令列表 用法: - ctrl + c / q : 停止此命令运行 - c : 展示完整的命令 - [top -bn1]:可以不动态的展示 ...

  6. [ python ] 网络编程(2)

    黏包问题 这样一个实例 import socket import subprocess sk_server = socket.socket() # 创建 socket对象 sk_server.bind ...

  7. java关键字(详解)

    目录 1. 基本类型 1) boolean 布尔型 2) byte 字节型 3) char 字符型 4) double 双精度 5) float 浮点 6) int 整型 7) long 长整型 8) ...

  8. Math类的数学计算功能

    //Math类的数学计算功能 public class MathTest { public static void main(String[] args) { /*----------下面是三角运算- ...

  9. POJ 3186Treats for the Cows(区间DP)

    题目链接:http://poj.org/problem?id=3186 题目大意:给出的一系列的数字,可以看成一个双向队列,每次只能从队首或者队尾出队,第n个出队就拿这个数乘以n,最后将和加起来,求最 ...

  10. Jmeter中的逻辑控制器(四)

    Jmeter中的逻辑控制器 (Logic Controller) [线程组]右键—>[添加]—>[逻辑控制器] 简单控制器(Simple Controller ) 没有特殊功能,目的是形成 ...