题目链接
题意
j
z
m
jzm
jzm和他的学妹在玩游戏,这个游戏共有
n
n
n轮,在第
i
i
i轮获胜会获得
i
i
i分,没有平局。
现在给出
j
z
m
jzm
jzm和学妹的得分,求是否有一种方案符合当前得分。
思路
首先我们可以知道,学妹和
j
z
m
jzm
jzm的分数之和一定是一个可以表示为
n
(
n
+
1
)
2
的
数
\frac{n(n+1)}{2}的数
2n(n+1)的数
对于如何查找,因为
n
n
n只有
1
e
5
1e5
1e5,故我们可以使用暴力来查找
当然,也可以通过二分来查找 (提升不明显)
若是找不到这样的一个
n
n
n,就可以直接输出
N
o
No
No了
接着我们考虑如何求出答案:
有一个显而易见的结论,
1
1
1 ~
n
n
n中任意取,可以取出
1
1
1 ~
n
(
n
+
1
)
2
\frac{n(n+1)}{2}
2n(n+1)中的所有数字
有了这个结论,我们就可以直接从大往小取,取到
a
a
a被取没了,就ok了
注意事项
∵
1
≤
a
,
b
≤
2
31
−
1
\because\ 1\le a,b\le\ 2^{31} - 1
∵ 1≤a,b≤ 231−1
∴
a
,
b
\therefore\ a, b
∴ a,b 都应该开
l
o
n
g
l
o
n
g
long\ long
long long
代码
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cstdlib>
#include <cctype>
#include <map>
#include <set>
#include <vector>
#include <iostream>
#include <cmath>
#define pk putchar(' ')
#define ph puts("")
#pragma GCC optimize(2)
using namespace std;
typedef long long ll;
template <class T>
void rd(T &x)
{
x = 0;
int f = 1;
char c = getchar();
while (!isdigit(c)) {if (c == '-') f = -1; c = getchar();}
while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
x *= f;
}
template <class T>
void pt(T x)
{
if (x < 0)
putchar('-'), x = (~x) + 1;
if (x > 9)
pt(x / 10);
putchar(x % 10 ^ 48);
}
template <class T>
T Max(T a, T b)
{
return a > b ? a : b;
}
template <class T>
T Min(T a, T b)
{
return a < b ? a : b;
}
const int N = 1e5 + 5;
ll a, b;
int main()
{
rd(a), rd(b);
b += a;
ll l = 0, r = 1e5;
while (l <= r)
{
ll mid = (l + r) >> 1, res = mid * (mid + 1) / 2;
if (res < b)
l = mid + 1;
else if (res > b)
r = mid - 1;
else
{
l = mid;
break;
}
}
if (l * (l + 1) / 2 != b)
{
puts("No");
return 0;
}
pt(l);
for (int i = l;i && a; i--)
if (a >= i)
{
a -= i;
pk;
pt(i);
}
return 0;
}