欧拉计划 Project Euler 73(分数有范围计数)题解
欧拉计划 Project Euler 73 题解
- 题干
- 分数有范围计数
- 思路
- code
题干
分数有范围计数
考虑形如 n d \frac{n}{d} dn的分数,其中 n n n和 d d d均为正整数。如果 n < d n<d n<d且其最大公约数为1,则称该分数为最简真分数。
将所有 d ≤ 8 d\leq8 d≤8的最简真分数构成的集合按大小升序排列:
1 8 , 1 7 , 1 6 , 1 5 , 1 4 , 2 7 , 1 3 , 3 8 , 2 5 , 3 7 , 1 2 , 4 7 , 3 5 , 5 8 , 2 3 , 5 7 , 3 4 , 4 5 , 5 6 , 6 7 , 7 8 \frac 1 8, \frac 1 7, \frac 1 6, \frac 1 5, \frac 1 4, \frac 2 7, \frac 1 3, \frac 3 8, \mathbf{\frac 2 5}, \frac 3 7, \frac 1 2, \frac 4 7, \frac 3 5, \frac 5 8, \frac 2 3, \frac 5 7, \frac 3 4, \frac 4 5, \frac 5 6, \frac 6 7, \frac 7 8 81,71,61,51,41,72,31,83,52,73,21,74,53,85,32,75,43,54,65,76,87
可以看出在 1 3 \frac{1}{3} 31和 1 2 \frac{1}{2} 21之间有 3 3 3个数。
将 d ≤ 12000 d\leq12000 d≤12000的最简真分数构成的集合中排序后,在 1 3 \frac{1}{3} 31和 1 2 \frac{1}{2} 21之间有多少个分数?
思路
这个题按照范围来说是可以暴力解决的,还有莫反也可以解决,这涉及到Farey序列,也可以用Stern-Brocot树解决。这里给出暴力的解法。
code
// 7295372
#include <bits/stdc++.h>using namespace std;using ll = long long;// 这段 lambda 内部的代码会在 main() 调用之前被执行。
int __OI_INIT__ = []() {ios::sync_with_stdio(0), cin.tie(0);cout.tie(0);cout << fixed << setprecision(12); // 设置输出浮点数默认精度为 12 位。return 0;
}();// 用法
/*int a = 1;double k = 2.0;string s = "hello world";_(a, k, s);输出 --->1 2.000000000000 hello world
*/
template<class... Args> void _(Args... args) {auto _ = [&](auto x) { cout << x << " "; };cout << "--->";int arr[] = {(_(args), 0)...};cout << "\n";
}void solve() {ll li = 12000;ll cnt = 0;for (int d = 1; d <= li; ++d) {int kmin = d / 3 + 1; // 分子下限int kmax = (d - 1) / 2;if (kmin > kmax) continue;for (int k = kmin; k <= kmax; ++k) {if (__gcd(k, d) == 1) {cnt++;}}}cout << cnt << "\n";
}int main() {int tt = 1;// cin >> tt;while (tt--) {solve();}}