数学上,n阶的法里数列是0和1之间最简分数的数列,由小至大排列,每个分数的分母不大于n。(百科上是这么写的的)
一阶:
0/1 1/1
二阶:
0/1 1/2 1/1
三阶:
0/1 1/3 1/2 2/3 1/1
........................................
七阶:
0/1 1/7 1/6 1/5 1/4 2/7 1/3 2/5 3/7 1/2 4/7 3/5 2/3 5/7 3/4 4/5 5/6 6/7 1/1
.................................
假设已知两个法里数a/b和c/d,那么两者之间的法里数就是(a+c)/(b+d)
例如 0/1和1/1之间的法里数就是1/2;
法里数列的个数:F(n) = F(n - 1) + eulor(n) (eulor:欧拉函数 f[0] = 1 );
例题:
Hdu4556:Stern-Brocot Tree法里数列个数:
#include<bits/stdc++.h>
typedef long long ll;
const int maxn = 5e5 + 5;
int phi[maxn * 2], prim[maxn * 2];
ll sum[maxn * 2];
void get_euler() {
memset(phi, 0, sizeof phi);
phi[1] = 1;
int id = 0;
for (int i = 2; i < maxn * 2; i++) {
if (!phi[i]) {
phi[i] = i - 1;
prim[id++] = i;
}
for (int j = 0; j < id && prim[j] * i < maxn * 2; j++) {
if (i % prim[j]) {
phi[i * prim[j]] = phi[i] * (prim[j] - 1);
} else {
phi[i * prim[j]] = phi[i] * prim[j];
break;
}
}
}
sum[0] = 0;
for(int i = 1; i < maxn * 2; i++)
sum[i] = sum[i - 1] + phi[i];
}
int main() {
get_euler();
int n;
while (scanf("%d", &n) != EOF) {
printf("%lld\n", sum[n] * 2 + 1);
}
return 0;
}
Upc5249输入k、m、x,找出分母不大于m的最接近x的分数。(分子分母互质)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main() {
int T;
scanf("%d", &T);
while (T--) {
int k, m;
double x;
scanf("%d%d%lf", &k, &m, &x);
printf("%d ", k);
int a = 0, b = 1, c = 1, d = 1, p = 0, q = 0;
while (b + d <= m) {
p = a + c;
q = b + d;
if (1.0 * p / q > x) {
c = p;
d = q;
} else {
a = p;
b = q;
}
}
if (fabs(1.0 * a / b - x) > fabs(1.0 * c / d - x))
printf("%d/%d\n", c, d);
else
printf("%d/%d\n", a, b);
}
return 0;
}