[传智杯 #5 初赛] E-梅莉的市场经济学

数据范围无法阻挡我求根公式的步伐QwQ


题意简述

有一个有规律的数列 \(a\)\([0],[0, 1, 0, -1, 0],[0, 1, 2, 1, 0, -1, -2, -1, 0]\dots\)\(q\) 次询问,每次询问求第 \(k\) 项。但是注意,\(k\) 是小于等于 \(4\times 10^{18}\) 的正整数。

题目分析

题意简述 里面,我们把由一对中括号括起来的数列称作一段,第 \(i\) 段的长度为 \(S_i\)。那么满足 \(S_i=S_{i-1}+4(i>1)\),且 \(S_1=1\)。满足等差数列性质,公差为 \(4\)。公式法求得,前 \(i\) 段的长度和为:

\[\frac {[1+1+4\cdot(i-1)]\cdot i} {2}={(2i-1)\cdot i} \]

那么第 \(k\) 项前面有多少段呢?设前面有 \(x\) 段(如果 \(k\) 为一段的末尾,该段也计算,否则不算),\(k\) 是所在段的第 \(y\) 项,那么 \(x\) 是满足 \((2x-1)\cdot x\leq k\) 的最大整数,\(y=k-(2x-1)\cdot x\)。特别的,当 \(y=0\) 时,第 \(k\) 项是所在段的最后一项。

解一元二次不等式 \((2x-1)\cdot x\leq k\),得 \(x\leq\frac {1+\sqrt {1+8k}}{4}\),即 \(x=\lfloor \frac {1+\sqrt {1+8k}}{4} \rfloor\)。知道了 \(x\)\(y\) 自然容易求解。

接着来求第 \(k\) 项的具体值。我们把一段按照单调性分为三段。那么满足:

\[a_k=\left\{ \begin{aligned} &0,& &y=0,\\ &y-1,& &0<y\leq x+1, \\ &2x+1-y,& &x+1<y\leq 3x+1, \\ &y-4x-1,& &otherwise. \end{aligned} \right. \]

大功告成!但是别急,数据范围要坑你。我们发现在极端情况 \(k=4\times 10^{18}\) 时,\(1+8k=3.2\times 10^{19}+1\),而 unsigned long long 范围大约是 \([0,1.8\times 10^{19}]\),爆范围了!怎么办呢?小技巧:

\[\sqrt {8k+1}=\sqrt 8\cdot\sqrt {k+0.125} \]

x=(1+sqrt(8)*sqrt(0.125+k))/4\(k+0.125\) 不会爆 double,\(8\) 更不会。那么问题迎刃而解了。

代码

#include<bits/stdc++.h>
using namespace std;
long long k,q;
signed main(){
	scanf("%lld",&q);
	while(q--){
		scanf("%lld",&k);
		long long x=(1+sqrt(8)*sqrt(0.125+k))/4,y=k-(2*x-1)*x;
		if(y==0){printf("0\n");continue;}
		if(y<=x+1)printf("%d\n",y-1);
		else if(y<=3*x+1)printf("%d\n",x*2+1-y);
		else printf("%d\n",y-4*x-1);
	}
	return 0;
}
posted @ 2022-11-27 11:23  robinyqc  阅读(33)  评论(0)    收藏  举报