ACM题解——训练赛1_F
题目描述
F - Jumping Jack
Jack is working on his jumping skills recently. Currently he's located at point zero of the number line. He would like to get to the point x. In order to train, he has decided that he'll first jump by only one unit, and each subsequent jump will be exactly one longer than the previous one. He can go either left or right with each jump. He wonders how many jumps he needs to reach x.
Input
The input data consists of only one integer x ( - 109 ≤ x ≤ 109).
Output
Output the minimal number of jumps that Jack requires to reach x.
Examples
Input
2
Output
3
Input
6
Output
3
Input
0
Output
0
题意
Jack可以往左或往右跳,第几次跳就跳几步,例如,第一次往左或往右跳一步,下一次就往左或往右跳两步,第三次就跳三步……起始位置是0。求达到坐标x的最短步数。
题解
这个题有一个巧妙的点,同一个步数往左、往右走会相差该步数的二倍,因此可以借此进行后退调整到想要的位置。首先我们一直往右走,第n次达到的位置为 ,先走到恰比x大的位置,这时走了n次,计算
, 给m进行分类,当m是偶数时,意味着这个差值通过调整m/2次的方向,改成向左跳就可以到达x,所以结果次数就是n;若m是奇数,就要查看一下下一次要跳的是奇数还是偶数,下一次跳n+1步,若是奇数,差值m+奇数就变成了了偶数,也可以通过改变中间(m+奇数)/2这一步的方向来走到x,则结果次数为n+1次;若n+1是偶数,则差值m+偶数还是奇数,则需要再走一步,n+2一定是奇数,差值m+偶数+奇数为偶数,中间某一步改变方向即可到达x,结果次数为n+2次。
当x为负方向位置时,就可以将x变为abs(x)继续相同方式求解即可。
代码
#include<iostream>
#include<cmath>
using namespace std;
int main()
{
long long int x=0;
cin>>x;
x=abs(x);
long long int n=sqrt(2*x);
long long int m=0;
if((n*(n+1)*0.5)<x) //求恰好到达x或超过x的次数n
{
m=(n+2)*(n+1)*0.5-x;
n++;
}
else
m=(n+1)*n*0.5-x;
if(m%2==0)
cout<<n<<endl;
else if(m%2!=0 && n%2==0)
cout<<n+1<<endl;
else
cout<<n+2<<endl;
return 0;
}