D. Pythagorean Triples(1487D)(打表找规律 + 二分)
题目来源:D. Pythagorean Triples
题意:
给定一个 n,求满足以下条件的数对 (a, b, c) 的个数
- 1 <= a <= b <= c <= n
- a * a + b * b = c * c
- c = a * a - b
思路:
这个题推公式也可以求,但当时太菜了没想到,而且题目还理解错了
通过打表我们发现(刚开始表还打错了)
- n = 1 ~ 4, ans = 0
- n = 5 ~ 12, ans = 1
- n = 13 ~ 24, ans = 2
- n = 24 ~ 40, ans = 3
- n = 41 ~ 60, ans = 4
- …
我们去记录最后一个数字会发现,他们相邻两个数之间的差为 8, 12, 16, …是公差为 4 的等差数列
我们记差值 a[i] = 8 + 4 * (i - 1), 其中 a[0] = 0, 那么答案为 i 所对应的最大的 n 就是 a 的前 i 项和再加 4(最开始的1 ~ 4没有算),也就是x = i * (8 + 8 + 4 * (i - 1)) / 2 + 4 = 2 * i * i + 6 * i + 4
我们去二分枚举出离 n 最近,并且大于等于 n 的 x, 最后输出 x 所对应的 i 即可
- 等差数列前 i 项和:项数 * (首项 + 末项) / 2
AC代码
#include <bits/stdc++.h>
#define endl "\n"
#define rep(i, m, n) for (int i = (m); i <= (n); ++i)
#define rrep(i, m, n) for (int i = (m); i >= (n); --i)
#define IOS ios::sync_with_stdio(0); cin.tie(0);
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int N = +10, mod = 1e9 + 7;
int n;
//等差数列前x项和 + 4
ll fact(ll x) { return (2 * x * x + 6 * x) + 4; }
void solve() {
cin >> n;
int l = 0, r = 1e6;
while (l < r) {
ll mid = l + r >> 1;
if (fact(mid) >= n) r = mid;
else l = mid + 1;
}
printf("%d\n", l);
}
int main() {
int t; cin >> t;
while (t--) solve();
return 0;
}