Stern-Brocot树
产生了所有分子分母互素的分数

从初始0/1 1/0 -> m/n m'/n'出发,不断往中间添加 (m+m')/(n+n')
容易推得 n * m' - m * n' = 1
证:
初始 0/1 1/0 那么1*1-0*0=1
那么假设前一次符合n * m' - m * n' = 1的性质
之后二叉树有两个方向行进,产生两种相邻 (m/n , (m+m')/(n+n')) ((m+m')/(n+n') , m'/n')
-> 左侧n*(m+m') - m*(n+n') = n*m'-m*n'=1
右侧(n+n')*m'-(m+m')*n' = n*m'-m*n = 1
所以总是不断的得到n * m' - m * n' = 1的性质

那么根据扩展欧几里得很容易得到 (n+n') , (m+m') 互质才有解,所以产生的数 (m+m')/(n+n') 必然是分子分母互素的

因为必然有整数解,很容易得知左右连接的两个数 n , n' 互质 , m m'互质 , n m 互质 , n' m'互质

同样因为(n+n')*m'-(m+m')*n' = 1
产生了所有分子分母互素的分数的证明:
m/n < (m+m')/(n+n') < m'/n' -> 这一点保证了Stern-Brocot树产生的分数是有序的
总是在两个合法分数之间产生一个合法分数,也就是说我们需要任何分数,只需要递归判断属于哪个区间,不断往树的那
一侧移动
而且每次往树底移动一步,必然会使分母变大至少1,所以求分母为n的合法分数,至多只需要往树上走n层即可


利用Stern-Brocot树思想 求解阶为n的法里级数
法里级数就是表示分母不大于n的所有分数

下面是简单的求出法里级数序列的代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
using namespace std;
#define M 26
#define N 500000
#define ull unsigned long long
#define ll long long
const int MOD = 1000000007;
int n;

void dfs(int l1 , int l2 , int r1 , int r2) //l1/l2 , r1/r2
{
    if(l2+r2>n) return ;
    //Stern-Brocot树 左侧总是最小的,右侧最大的,那么总是优先输入左侧,再输入中间的,最后输入右侧的数
    dfs(l1 , l2 , l1+r1 , l2+r2);
    cout<<l1+r1<<"/"<<l2+r2<<" ";
    dfs(l1+r1 , l2+r2 , r1 , r2);
}

int main() {
    n = 7;
    cout<<"0/1 ";
    dfs(0 , 1 , 1 , 1); //会按从小到大的次序输出结果
    cout<<"1/1"<<endl;
    return 0;
}
Farey series

相关文章:

  • 2022-12-23
  • 2021-07-28
  • 2022-12-23
  • 2021-12-08
  • 2022-12-23
  • 2022-12-23
  • 2021-06-27
  • 2021-05-14
猜你喜欢
  • 2021-07-21
  • 2022-12-23
  • 2021-04-01
  • 2022-12-23
相关资源
相似解决方案