题目链接
题意
和他的学妹在玩游戏,这个游戏共有
轮,在第
轮获胜会获得
分,没有平局。
现在给出
和学妹的得分,求是否有一种方案符合当前得分。
思路
首先我们可以知道,学妹和
的分数之和一定是一个可以表示为
对于如何查找,因为
只有
,故我们可以使用暴力来查找
当然,也可以通过二分来查找 (提升不明显)
若是找不到这样的一个
,就可以直接输出
了
接着我们考虑如何求出答案:
有一个显而易见的结论,
~
中任意取,可以取出
~
中的所有数字
有了这个结论,我们就可以直接从大往小取,取到
被取没了,就ok了
注意事项
都应该开
代码
#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;
}