利用广义欧几里得除法解决法雷数列问题
问题如下:
对任意给定的一个自然数n,将分母小于等于n的不可约的真分数按升序排列,并且在第一个分数之前加上0/1,在最后一个分数之后加上1/1,这个序列称为n级法雷数列,以Fn表示。如F5为:0/1,1/5, 1/4, 1/3, 2/5, 1/2, 3/5, 2/3, 3/4, 4/5,1/1.其元素个数为11.
现在给出n让你求其n级法雷数列中元素的排列和个数。
解决思路:
利用广义欧几里得除法求取分子和分母的最大公因数,输出最大公因数为1的分式(不可约分),然后将分式转化为小数比较大小并利用冒泡排序对其从小到大排列,最后以分式形式输出。
源代码分享如下:
#include <stdio.h>
#include <stdlib.h>
#define N 1000
int QuYu(int num1, int num2)
{
int num3 = 1; //余数
for(; num3 > 0;)
{
num3 = num1 % num2;
num1 = num2;
num2 = num3;
}
return num1; //返回最大公因数
}
int main()
{
int QuYu(int, int); //定义广义欧几里得函数
int num1 = 0; //要进行操作的数字
int tempi; //冒泡排序中间变量
int tempj;
double tempnum2;
int i = 0;
double i1 = 0; //整形类型无法除出小数,在分数转小数时作为中间变量,和分子i同步
int j = 0;
double j1 = 0; //和分母j同步
int k = 0; //结构体数组Data的下标
int m = 0; //计数器,计算此法雷数列除去 0/1 ,还有多少个元素
struct Data //定义一个结构体数组,用来存储分数的值和其对应的分子分母
{
double num2; //存储真分数的值,用来比较大小
int numi; //每个数据对应的i,也就是分子
int numj; //每个数据对应的j,也就是分母
}data[N];
printf("输入一个要求其法雷数列的整数:");
scanf("%d", &num1);
//将符合法雷数列的分数的值,以及其分子分母进行存储
for(i = 1, i1 = 1; i <= num1; i++, i1++) //i表示分子
{
for(j = 1, j1 = 1; j <= num1; j++, j1++) //j表示分母
{
if(i == 1) //任何非0数对0取余都为0,所以讲i=1的情况单独拿出来
{
data[k].num2 = (i1 / j1);
data[k].numi = i;
data[k].numj = j;
k++; //结构体数组的下标
m++; //计数,总共有几个分数产生,作为后边循环的终止条件
}
else
{
if(i < j && QuYu(j, i) == 1) //要求是真分数,并且最大公因数为1
{
data[k].num2 = (i1 / j1);
data[k].numi = i;
data[k].numj = j;
k++;
m++;
}
}
}
}
//对所有符合条件的分数进行大小排序
for(i = 0; i < m - 1; i++) //外层循环控制冒泡排序的轮数
{
for(j = 0; j < m - i - 1; j++) //内层循环控制每轮循环的次数
{
if(data[j].num2 > data[j + 1].num2)
{
//利用3个中间变量,在冒泡排序后,将结构体数组中的3个值进行转移
tempnum2 = data[j].num2;
data[j].num2 = data[j + 1].num2;
data[j + 1].num2 = tempnum2;
tempi = data[j].numi;
data[j].numi = data[j + 1].numi;
data[j + 1].numi = tempi;
tempj = data[j].numj;
data[j].numj = data[j + 1].numj;
data[j + 1].numj = tempj;
}
}
}
//输出结果,在第一个之前输出0/1
printf("\n%d的法雷数列共有%d个元素,如下:\n\n", num1, m + 1);
printf("0/1 ");
for(i = 0; i < m; i++)
{
printf("%d/%d ",data[i].numi, data[i].numj);
}
return 0;
}
运行结果:
以上就是关于解决法雷数列问题的一种思路,望大佬多多指教,小白从中受益!