Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/131.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 按分母和分子的升序求两个给定分数之间的不可约分数_C++_Algorithm_Performance_Optimization_Fractions - Fatal编程技术网

C++ 按分母和分子的升序求两个给定分数之间的不可约分数

C++ 按分母和分子的升序求两个给定分数之间的不可约分数,c++,algorithm,performance,optimization,fractions,C++,Algorithm,Performance,Optimization,Fractions,每次测试的时间限制:2秒 每次测试的内存限制:512 MB 您将获得两个分数a/bc/d和一个正数N。 考虑所有不可约分数 E/F < /代码>,使 0 < e,f≤ N和 a/be/fc/d。设s为这些分数的序列 按分母和分子(分数)的升序排序 e1/f1在e2/f2之前,如果f1b>>c>>d>>N>>N; 计算机结果(); cout应该迭代从1到N的所有分母,但不需要迭代给定范围内的所有分子 对于任何不可约分式分子/分母,分子和分母都是。所以你需要的是有效地生成分母的所有余素数/分母在给定

每次测试的时间限制:2秒
每次测试的内存限制:512 MB

您将获得两个分数
a/b
c/d和一个正数
N
。 考虑所有不可约分数<代码> E/F < /代码>,使<代码> 0 < e,f≤ N和
a/b
e/f
c/d
。设
s
为这些分数的序列 按分母和分子(分数)的升序排序
e1/f1
e2/f2
之前,如果
f1
f1=f2和e1
)。您应该首先打印序列中的
n
s
或 整个序列
s
,如果它包含少于
n个
术语

输入
每个测试的第一行包含6个整数
a
b
c
d
N
N
0≤ A.≤ 10^18
1≤ b、 c,d,N≤ 10^18
1≤ N≤ 200000
a/b

输出
首先,打印您将输出多少个序列项
s
。然后按正确的顺序输出这些术语

示例

  • 输入: 输出:
  • 输入: 输出:
  • 输入: 输出:
到目前为止,我只写了一个解决方案,迭代从
1
N
的所有分母,并为每个分母迭代从
a*f/b
c*f/d
的所有分子,将所有找到的不可约分数添加到答案中

这是我的密码:

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

long long a, b, c, d, N, n;
vector<pair<long long, long long>> result;

long long gcd(long long a, long long b) {
    while (b) {
        a %= b;
        swap(a, b);
    }
    return a;
}

void computeResult() {
    for (long long f = 1; f <= N; f++) {
        long long eMax = c*f / d;
        if (c*f % d != 0) eMax++;
        eMax = min(eMax, N);
        for (long long e = a*f / b + 1; e < eMax; e++) {
            if (gcd(e, f) == 1) {
                result.push_back(make_pair(e, f));
                if (result.size() == n)
                    return;
            }
        }
    }
}

int main() {
    cin >> a >> b >> c >> d >> N >> n;  
    computeResult();
    cout << result.size() << endl;
    for (pair<long long, long long> fraction : result)
        cout << fraction.first << " " << fraction.second << endl;
}
#包括
#包括
#包括
使用名称空间std;
长a,b,c,d,N,N;
矢量结果;
长-长gcd(长-长a,长-长b){
而(二){
a%=b;
掉期(a、b);
}
返回a;
}
无效计算机结果(){
对于(长f=1;f>a>>b>>c>>d>>N>>N;
计算机结果();

cout应该迭代从1到N的所有分母,但不需要迭代给定范围内的所有分子

对于任何不可约分式分子/分母,分子和分母都是。所以你需要的是有效地生成分母的所有余素数/分母在给定范围内的余素数

例如,对于分母=8,余数是1,3,5,7。范围[0,1]中的不可约分数是1/8、3/8、5/8、7/8。您可以通过向其添加整数来扩展不可约分数的范围:1+1/8、1+3/8、1+5/8、1+7/8=>9/8、11/8、13/8、15/8是范围[0+1,1+1]=>1,2]中以8为分母的不可约分数

用于生成x的所有余项的伪代码,以使a/b<余项/x
prime_factors_of_x = get_prime_factors(x)
is_coprime = boolean array of size x
set every element of is_coprime to True
// next, set to False all elements indexed by multiples of a prime factor of x
for every factor in prime_factors_of_x:
   // next loop can be a vectorial operation in some languages
   for i in 0..(x/factor):
      is_coprime[i*factor] = False

all_coprime_list = [] // empty list
min_coprime = floor(a/b * x)+1
max_coprime = floor(c/d * x)-1
for i in min_coprime..max_coprime:
   if is_coprime[i mod x]:
      all_coprimes_list.append(i)

这就是总体思路。

这是一个非常有趣的问题,我真的很喜欢思考它,我不知道为什么它会收到这么多反对票。不管怎样,下面是我对解决方案的粗略描述。如果我对它进行了一些改进,我将在稍后更新我的答案


正如所建议的,我们需要一种更有效的方法来生成coprimes


定义:
a/b
c/d
之间的顺序
n
是升序(按值)不可约分数的序列
p/q
,这样
a/b除了另一个问题,你会注意到如果
N=10^9
,它排序是有效的,但是如果
N=10^18
,那么你的代码在乘以f时会溢出,所有的东西都会散开。你可以做
long-long eMax=(long-long)((long-double)c)*f/d);

(下限也是如此)来减少这个问题,但它会减慢它的速度。

我认为这不是解决这个问题的合适平台。如果你想查看你的代码/算法(为了效率等),是正确的平台。请将您的问题转移到那里。@AjayDabas我不想查看我的代码/算法。我知道它很慢。我正在寻找另一个更有效的解决方案。请给出此问题的来源?可以在线测试解决方案吗?@Evg,很遗憾,注册有限。在mai结束时进行迭代时n、 make是
&分数
以避免无用的副本。也可以在main的开头尝试
结果
的预分配空间。哦,不要使用
endl
,我怎样才能有效地生成分母的所有余素数/分母位于给定范围内的余素数?@Bananon,我希望我的伪代码有帮助。我会写我的在C++中,如果我可以的话,我是一个Python的家伙。谢谢这个优化的想法。我会赞成你的答案。但是我想指出你的算法比检查<代码> GCD(x,i)更有效。
对于
min\u copinite..max\u copinite
中的每个
i
仅当
max\u copinite-min\u copinite
相对较大时。因此,我建议根据
x
max\u copinite-min\u copinite
的值动态选择一种算法。不幸的是,这种优化仍然不足以通过最小
a、b、c、d、N≤ 10^9,n≤ 1000
一组测试。在我的python测试中,一旦你可以做一个向量运算的内环,这个算法就快多了。它实际上变成了线性的。在python/numpy中,我们写
是互质[::因子]=[False]*len(是互质[::因子])
。在第一个解决方案中,在嵌套循环中调用GCD,这似乎是二次复杂度。无论如何,为了进一步改进它,我会缓存一些计算结果。刚刚实现了如何更详细地指定算法并使序列顺序具有确定性,总体复杂度
O((logn+logn)*n)
。明天将更新我的答案。Stern Brocot树
55 34 68 42 90 1
1
89 55
49 33 45 30 50 239
0
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

long long a, b, c, d, N, n;
vector<pair<long long, long long>> result;

long long gcd(long long a, long long b) {
    while (b) {
        a %= b;
        swap(a, b);
    }
    return a;
}

void computeResult() {
    for (long long f = 1; f <= N; f++) {
        long long eMax = c*f / d;
        if (c*f % d != 0) eMax++;
        eMax = min(eMax, N);
        for (long long e = a*f / b + 1; e < eMax; e++) {
            if (gcd(e, f) == 1) {
                result.push_back(make_pair(e, f));
                if (result.size() == n)
                    return;
            }
        }
    }
}

int main() {
    cin >> a >> b >> c >> d >> N >> n;  
    computeResult();
    cout << result.size() << endl;
    for (pair<long long, long long> fraction : result)
        cout << fraction.first << " " << fraction.second << endl;
}
prime_factors_of_x = get_prime_factors(x)
is_coprime = boolean array of size x
set every element of is_coprime to True
// next, set to False all elements indexed by multiples of a prime factor of x
for every factor in prime_factors_of_x:
   // next loop can be a vectorial operation in some languages
   for i in 0..(x/factor):
      is_coprime[i*factor] = False

all_coprime_list = [] // empty list
min_coprime = floor(a/b * x)+1
max_coprime = floor(c/d * x)-1
for i in min_coprime..max_coprime:
   if is_coprime[i mod x]:
      all_coprimes_list.append(i)
k = int((n + b0) / b1)
a2 = k * a1 - a0
b2 = k * b1 - b0
k = ceil(sqrt(n * pi^2)) + C
1. Estimate the order k of the Farey Sequence to generate, such that |F_k| >= n
2. Calculate the second element of F_k. O(k), where k << n and 1 < n < 200000
3. Generate the whole Farey Sequence. O(n), where 1 < n < 200000
4. Sort by the requirements. O(n log n), where 1 < n < 200000