UPC-双头巨人 (twin)

世 上 没 有 绝 望 的 处 境
只 有 对 处 境 绝 望 的 人

UPC-双头巨人(twin)戳这里跳转至题解

题目描述

老爹说要用魔法打败魔法 ———— 3edc2wsx1qaz
一天,巨神 3edc2wsx1qaz 正在森林里漫步,突然,一只凶恶的双头巨人拦住了他。
双头巨人的两个头的攻击力分别为a,b。它每次可以对 3edc2wsx1qaz 造成 |a-b| 的魔法伤害。
3edc2wsx1qaz 觉得这只怪物十分难缠。
“要用魔法打败魔法!” 就在这时,老爹的话回响在 3edc2wsx1qaz 的耳边,3edc2wsx1qaz 顿时感到一股力量涌上心头,于是,他决定从它的特殊能力下手,从而打败它。
998244353年前,巨神 Rainy7 曾经教过他名为 爪巴 的 魔法,他决定用这种 魔法击败巨人。
3edc2wsx1qaz 可以使用无限次法术,第i次使用可以任选一个头,使得它的攻击力增加或减少i。(在此过程中攻击力可以是负数)
3edc2wsx1qaz 不想受到任何伤害,所以,他想知道,他至少要施几次法,才能使得a-b=0。
3edc2wsx1qaz 只用了114514-1919810 s就解决了这个问题,于是让您解决。

输入

第一行一个数T,表示数据组数。
对于每组数据,一行两个数a,b,代表双头巨人两个头的攻击力。

输出

对于每组数据,一行一个整数,表示最小次数。

Sample Input

4
1 3
11 11
30 20
114514 1919810

Sample Output

3
0
4
1900

思路分析

题目的要求是填补差值。那么咱们就来看如何去构造差值。
比如1 3这两者的差值是2,而且他增加的方式是一回合增加一个数,这个数是当前回合数。意思就是填补的数值顺序是1 2 3 4 5…… n,也就是说an=n

那么这题的要求就可以理解为,an=n这个等差数列,如何将前n项中的n个数分成两组,且差值为题目要求的差值。注意:我们可以找到很多个n使前n项分成两组,使得差值满足要求。那么这里就是要寻找最小的那个n

通过多组的暴力试验我们很容易发现如下规律:

  • 前n项和总是先两个奇数,之后两个偶数。
           这里可以证明,其实一想也能明白,无非就是奇数+奇数,偶数+偶数,奇数+偶数那一套,这里并不是关键。

  • 若为前n项和为奇数,则其可构成的差值的绝对值有

    1、3、5、7……Sn
    若为前n项和为偶数数,则其可构成的差值的绝对值有

    0、2、4、6……Sn
    详情见下表:

n 总和 差值
1 1 1
2 3 1、3
3 6 0、2、4、6
4 10 0、2、4、6、8、10
5 15 1、3、5、7、9、11、13、15
6 21 1、3、5、7、9、11、13、15、17、19、21
7 28 0、2、4、6、8、10、12、14、16、18、20、22、24、26、28

所以咱们当前的任务是寻找第一个可以构成的差值的n,这里注意奇数和偶数
对于1 3这两个数而言,差值为2,第一个可以构造出2的是n为3时。

答案即为3。

AC时间到

#include
#include
#include
#include 
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#pragma warning(disable:4244)
#define PI 3.141592653589793
#pragma GCC optimize(2)
#define accelerate cin.tie(NULL);cout.tie(NULL);ios::sync_with_stdio(false);
#define EPS 1.0e-8
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll ll_inf = 9223372036854775807;
const int int_inf = 2147483647;
const short short_inf = 32767;
const char char_inf = 127;
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
inline ll read() {
	ll c = getchar(), Nig = 1, x = 0;
	while (!isdigit(c) && c != '-')c = getchar();
	if (c == '-')Nig = -1, c = getchar();
	while (isdigit(c))x = ((x << 1) + (x << 3)) + (c ^ '0'), c = getchar();
	return Nig * x;
}
inline void out(ll a) {
	if (a < 0)putchar('-'), a = -a;
	if (a >= 10)out(a / 10);
	putchar(a % 10 + '0');
}
ll phi(ll n)
{
	ll ans = n, mark = n;
	for (ll i = 2; i * i <= mark; i++)
		if (n % i == 0) { ans = ans * (i - 1) / i; while (n % i == 0)n /= i; }
	if (n > 1)ans = ans * (n - 1) / n; return ans;
}
ll qpow(ll x, ll n, ll mod) {
	ll res = 1;
	while (n > 0) {
		if (n & 1)res = (res * x) % mod;
		x = (x * x) % mod;
		n >>= 1;
	}
	return res;
}
ll mat_mod;
struct Mat {
	ll m[10][10];
};
Mat Mul(Mat A, Mat B, ll mat_size) {
	Mat res;
	memset(res.m, 0, sizeof(res.m));
	for (int i = 0; i < mat_size; i++)for (int j = 0; j < mat_size; j++)for (int k = 0; k < mat_size; k++)
		res.m[i][j] = (res.m[i][j] + (A.m[i][k] * B.m[k][j]) % mat_mod) % mat_mod;
	return res;
}
Mat mat_qpow(Mat data, ll power, ll mat_size) {
	Mat res;
	memset(res.m, 0, sizeof(res.m));
	for (int i = 0; i < mat_size; i++)res.m[i][i] = 1;
	while (power) {
		if (power & 1)res = Mul(res, data, mat_size);
		data = Mul(data, data, mat_size), power >>= 1;
	}
	return res;
}
#define Floyd for(int k = 1; k <= n; k++)for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)
#define read read()
void solve()
{
	ll a = read, b = read;
	ll temp = abs(a - b);
	ll kind = sqrt(temp * 2);
	ll ans = (kind + 1) * kind / 2;
	if (ans < temp)kind++;
	if (temp & 1)
		while (kind % 4 == 3 || kind % 4 == 0)kind++;
	else
		while (kind % 4 == 1 || kind % 4 == 2)kind++;
	out(kind);
	puts("");
}
int main()
{
	ll T = read;
	while (T--)solve();
}

By-轮月

你可能感兴趣的:(ACM,算法,中国石油大学OJ)