法里数列
定义:
数学上,n阶的法里数列是0和1之间最简分数的数列,由小至大排列,每个分数的分母不大于n
\(F(1)=\{\frac{0}{1},\frac{1}{1}\}\)
\(F(2)=\{\frac{0}{1},\frac{1}{2},\frac{1}{1}\}\)
\(F(3)=\{\frac{0}{1},\frac{1}{3},\frac{1}{2},\frac{2}{3},\frac{1}{1}\}\)
\(F(4)=\{\frac{0}{1},\frac{1}{4},\frac{1}{3},\frac{1}{2},\frac{2}{3},\frac{3}{4},\frac{1}{1}\}\)
\(F(5)=\{\frac{0}{1},\frac{1}{5},\frac{1}{4},\frac{1}{3},\frac{2}{5},\frac{1}{2},\frac{3}{5},\frac{2}{3},\frac{3}{4},\frac{4}{5},\frac{1}{1}\}\)
性质:
n阶的法里数列包\(F_n\)包含了较低阶法里数列的全部项,特别是包含了\(F_{n-1}\)的全部项以及与\(n\)互质的每个数的相应分数,所以\(F_n\)和\(F_{n-1}\)的长度的关系,可以用欧拉函数\(\varphi(n)\)描述:
\(|F_n|=|F_{n-1}|+\varphi(n)\)
由\(|F_1|=2\)可得
\(|F_n|=1+\sum\limits_{i=1}^{n}\varphi(i)\)
\(|F_n|\)的渐进行为是:
\(|F_n|=\frac{3n^2}{\pi^2}\)
关于数列相邻项
若\(\frac{a}{b}\)与\(\frac{c}{d}\)是法里数列的邻项,且\(\frac{a}{b}<\frac{c}{d}\),那么他们之差是\(\frac{1}{bd}\),即\(bc-ad=1\)
逆命题同样成立,若\(bc-ad=1\),其中\(a,b,c\)和\(d\)为正整数,及有\(a<b,c<d\)则\(\frac{a}{b}\)与\(\frac{c}{d}\)在阶为\(max(d,b)\)的法里数列中是邻项
如何生成n阶的法雷序列:
利用Stern Brocot Tree生成
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/hash_policy.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/trie_policy.hpp>
using namespace __gnu_pbds;
using namespace std;
// freopen("k.in", "r", stdin);
// freopen("k.out", "w", stdout);
// clock_t c1 = clock();
// std::cerr << "Time:" << clock() - c1 <<"ms" << std::endl;
//#pragma comment(linker, "/STACK:1024000000,1024000000")
mt19937 rnd(time(NULL));
#define de(a) cout << #a << " = " << a << endl
#define rep(i, a, n) for (int i = a; i <= n; i++)
#define per(i, a, n) for (int i = n; i >= a; i--)
#define ls ((x) << 1)
#define rs ((x) << 1 | 1)
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef pair<char, char> PCC;
typedef pair<ll, ll> PLL;
typedef vector<int> VI;
#define inf 0x3f3f3f3f
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll MAXN = 1e3 + 7;
const ll MAXM = 4e5 + 7;
const ll MOD = 1e9 + 7;
const double eps = 1e-7;
const double pi = acos(-1.0);
struct Stern_Brocot_Tree
{
int n;
vector<PII> SB_Tree;
void init(int x)
{
n = x;
vector<PII>().swap(SB_Tree);
SB_Tree.emplace_back(0, 1);
}
void dfs(int l1, int l2, int r1, int r2)
{
if (l2 + r2 > n)
return;
dfs(l1, l2, l1 + r1, l2 + r2);
SB_Tree.emplace_back(l1 + r1, l2 + r2);
dfs(l1 + r1, l2 + r2, r1, r2);
}
void Build() //构造n阶法雷数列
{
dfs(0, 1, 1, 1);
SB_Tree.emplace_back(1, 1);
}
} SBT;
int main()
{
SBT.init(5);
SBT.Build();
for (auto i : SBT.SB_Tree)
printf("%d/%d ", i.first, i.second);
puts("");
return 0;
}