文章目录
- 题目链接
- 题意
- 思路
- 注意事项
- 代码
- 题目链接
- Thanks!
题目链接
题意
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;
}