题目背景
梅莉这个学期选修了经济学。但是主修心理学的她实在不擅长经济领域的分析,为此她时常抱怨自己学不会,想退课。
但是如果现在退掉的话这学期的学分就不够啦,因此她根据“梦中”的经历,“胡诌”了一个简单到不现实的市场模型,并依据这个模型编起了 essay。为了方便地编出图表,她需要写一个程序来查询每个时刻的市场贸易差。
题目描述
市场每一天的贸易差可以视为一个有周期性规律的数列 𝑎: [0],[0,1,0, −1,0],[0,1,2,1,0, −1, −2, −1,0],[0,1,2,3,2,1,0, −1, −2, −3, −2, −1,0] … 具体而言 , 𝑎 可以被分为无穷段,第 𝑖 段的内容为 0,1, … , 𝑖, 𝑖 − 1, … ,0, −1, … , −𝑖, −𝑖 + 1, … ,0。如下图所示,是将 𝑎 数 列内的前一些点绘制在坐标轴上的情况:
现在梅莉对市场发起了 𝑞 次询问,每次她会给定一个 𝑘,希 望求出 𝑎𝑘 是多少。
输入格式
第一行有一个正整数 𝑞,表示询问次数。 接下来 𝑞 行,每行一个正整数 𝑘,描述每次询问
输出格式
输出共 𝑞 行。对于每次询问,输出对应的结果。
数据规模 对于所有数据,1 ≤ 𝑞 ≤ 10^5,1 ≤ 𝑘 ≤ 4 × 10^18。
Input
9
1
10
100
1000
10000
100000
1000000
10000000
100000000
Output
0
1
6
-9
-11
-128
406
1629
5154
解析:找规律,一个正三角和一个负三角看成一组,然后可以发现第N组的最高点就是N,然后推导出~第N组的起点下标就是(2*N-1)*N+1,同时结束下标也同理得到(2*N-1)*N+4*N+1,所以问题就是先转为给定k,先求出他在第几组之内,然后磨了一个小时也不知道怎么确定,然后试了一下二分,然后枚举第m组,如果k在他起点到终点的范围内,那么就可以说明k在第m组中,然后再判断一下高度即可。
#include <stdio.h>
#include <math.h>
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
long long x;
scanf("%lld",&x);
if(x==1)//1是0,直接特判了
{
printf("0\n");
continue;
}
x--;//方便一点,相当于将整体往前挪1
long long l=1,r=2000000000,ge;
while(l<=r)
{
long long m=l + (r - l) / 2;
if((2*m-1)*m<=x&&x<=(2*m-1)*m+4*m)
{
ge=m;
break;
}
if((2*m-1)*m>x) r=m-1;
else l=m+1;
}
//得出的ge就是k在第ge组中
long long start=(2*ge-1)*ge,p=ge;
if(x<=start+p) printf("%lld\n",x-start);//x在上左
else if(x<=start+2*p) printf("%lld\n",start+2*p-x);//x在上右
else if(x<=start+3*p) printf("%lld\n",-1*(x-(start+2*p)));//x在下左
else printf("%lld\n",-1*(start+4*p-x));//x在下右
}
return 0;
}