Project Euler 198

Project Euler 198

题目

Ambiguous Numbers

A best approximation to a real number $x$ for the denominator bound $d$ is a rational number $\dfrac{r}{s}$ (in reduced form) with $s \le d$, so that any rational number $\dfrac{p}{q}$ which is closer to $x$ than $\dfrac{r}{s}$ has $q > d$.

Usually the best approximation to a real number is uniquely determined for all denominator bounds. However, there are some exceptions, e.g. $\dfrac{9}{40}$ has the two best approximations $\dfrac{1}{4}$ and $\dfrac{1}{5}$ for the denominator bound $6$. We shall call a real number $x$ ambiguous, if there is at least one denominator bound for which $x$ possesses two best approximations. Clearly, an ambiguous number is necessarily rational.

How many ambiguous numbers $x=\dfrac{p}{q}$, $0 < x < \dfrac{1}{100}$, are there whose denominator $q$ does not exceed $10^8$?

解决方案

如果存在一个正整数$m$,使得两个分数$x=\dfrac{a}{c},y=\dfrac{b}{d}$在第$m$个Farey序列是相邻的。那么$\dfrac{x+y}{2}$很明显是一个答案。

因此,可以考虑对Stern-Brocot Tree进行遍历,枚举出Farey序列中有可能在Farey序列中相邻的分数,并统计。

令$R=100$。为了减少枚举量,对于枚举出的两个分数$x,y$,如果$x\ge\dfrac{1}{R}$,那么没有必要在这个区间上继续寻找答案(此时这里计算出来的$\dfrac{x+y}{2}$都大于$\dfrac{1}{R}$,不合题意)。

另外,由于直接使用递归会造成栈溢出(分析代码不难知道,最大的递归深度将会达到$O(N)$级别),因此这里使用非递归的方式遍历Stern-Brocot Tree.

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N=100000000;
const int R=100;
struct S{
ll a,c,b,d;
};
int main(){
int ans=0;
stack<S>st;
st.push(S{0,1,1,1});
while(!st.empty()){
S s=st.top();st.pop();
ll a=s.a,b=s.b,c=s.c,d=s.d;
if(c*d*2>N) continue;
// 左边的分数已经大于等于1/R,没必要取下去。
if(a*R>=c) continue;
ll p=a+b,q=c+d;
ll u=a*d+b*c,v=c*d*2;
if(u*R<v) ++ans;
st.push(S{a,c,p,q});
st.push(S{p,q,b,d});
}
printf("%d\n",ans);
}

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
Ujimatsu Chiya 微信 微信
Ujimatsu Chiya 支付宝 支付宝