洛谷P8873-E-梅莉的市场经济学

题目背景

梅莉这个学期选修了经济学。但是主修心理学的她实在不擅长经济领域的分析,为此她时常抱怨自己学不会,想退课。

但是如果现在退掉的话这学期的学分就不够啦,因此她根据“梦中”的经历,“胡诌”了一个简单到不现实的市场模型,并依据这个模型编起了 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;
}

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值