回 帖 发 新 帖 刷新版面

主题:第36次编程比赛第1题题目

法雷序列:
对任意给定的一个自然数n,将分母小于等于n的不可约的真分数按升序排列,
并且在第一个分数之前加上数0/1,在最后一个分数之后加上1/1,这个序列
称为n级法雷序列,以Fn表示。例如,F8为:
0/1, 1/8, 1/7, 1/6, 1/5, 1/4, 2/7, 1/3, 3/8, 2/5, 3/7, 1/2, 4/7, 3/5, 
5/8, 2/3, 5/7, 3/4, 4/5, 5/6, 6/7, 7/8, 1/1。

请编程输出任意的Fn序列。

函数原型:
// n - 序列级数
// farey[] - 存放Fn序列,以','分隔
void FareySequence(int n, char farey[]);

例:
输入:
5

数组中存放结果为:
0/1,1/5,1/4,1/3,2/5,1/2,3/5,2/3,3/4,4/5,1/1

回复列表 (共32个回复)

沙发

/*************
写了个可能效率比较低的  呵呵
还要麻烦boxertony兄把各个辅助函数调用一下 = =~|||
**************/

#include <iostream>
using namespace std;

typedef struct score
{
    int child;
    int mother;
    float value;
    score *pre;
    score *next;
}score;
score *head;

score *compair(score *x1,float s)
{
    score *h=x1;
    while(h->next!=NULL)
    {
        if(h->next->value<s)
            break;
        h=h->next;
    }
    return h;
}

int search(int s,int l)
{
    int i=2;
    for(;i<=s;i++)
    {
        if(0==s%i)
            if(0==l%i)
                return 0;
    }
    return 1;
}

void FareySequence(int n, char farey[])
{
    score *p1,*p2;
    int i,j;
    float temp;    
    head = new score;
    head->child=1;
    head->mother=n;
    head->value=(float)head->mother;
    p1=head;
    score *Tp = head;
    for(i=n-1;i>1;i--)
    {
        p2=p1;
        p1 = new score;
        p1->child=1;
        p1->mother=i;
        p1->value=(float)p1->mother;
        p2->next=p1;
    }
    p1->next=NULL;
    for(i=2;i<n;i++,Tp=head)
    {
        for(j=n;j>i;j--)
        {
            if(0==search(i,j))
                continue;
            temp=(float)j/i;
            Tp = compair(Tp,temp);
            p1 = new score;
            p1->child = i;
            p1->mother = j;
            p1->value = temp;
            if(Tp->next!=NULL)
                p1->next=Tp->next;
            else p1->next = NULL;
            Tp->next = p1;
            

        }
    }
    p1=head;
    farey[0] = '0';
    farey[1] = '/';
    farey[2] = '1';
    farey[3] = ',';
    int k=4;
    char brr[10];
    int l=0;
    while(p1!=NULL)
    {
        if(p1->child<10)
            farey[k++] = p1->child+'0';
        else
        {
            while(p1->child!=0)
            {
                brr[l++]=p1->child%10+'0';
                p1->child=p1->child/10;
            }
            l--;
            while(l>=0)
            {
                farey[k++] = brr[l--];
            }
        }
        l=0;
        farey[k++] = '/';
        if(p1->mother<10)
            farey[k++] = p1->mother+'0';
        else
        {
            while(p1->mother!=0)
            {
                brr[l++]=p1->mother%10+'0';
                p1->mother=p1->mother/10;
            }
            l--;
            while(l>=0)
            {
                farey[k++] = brr[l--];
            }
        }
        l=0;
        farey[k++] = ',';
        p1 = p1->next;
    }
    farey[k++] = '1';
    farey[k++] = '/';
    farey[k++] = '1';
    farey[k++] = '.';
    farey[k] = '\0';
}



main()
{
    char farey[2000];
    FareySequence(8,farey);
    cout<<farey;
}
//发现大于9的数没存好,修改了一下 呵呵[em2]

板凳

#include<stdlib.h>
#include <stdio.h> 
#include <string.h> 
/////////////(我自己用的测试的main函数)////////////
void FareySequence(int n, char farey[]);
int main()
{char str[30000];
 FareySequence(8,str);
 printf("%s",str);
 system("pause");
 return 1;
}
/////////////////////////////////////////////////
void FareySequence(int n, char farey[])
{
    struct Farey{float value; char moden[5];} Moden[10000];//也许不用这么大? 
    Farey temp; 
    int i,j,l,p=0;
    int x,y,z;
    l=sprintf(farey,"0/1,");
    for(i=1;i<n;i++)
        for(j=i+1;j<=n;j++)
        {   
            z=2;     //赋初值,使while循环能够执行     
            if(i!=1)
            {       
             x=j;
             y=i;
             while(z!=0&&z!=1)
             {
                z=x%y;
                x=y;
                y=z;
             }         
            } 
            if(z==0) continue;  //为0表示有公约数 
            Moden[p].value=float(i)/float(j);
            sprintf(Moden[p++].moden,"%d/%d,",i,j);
    }
    for(i=0;i<p;i++)   //最笨的方法,给数列排序 
        for(j=i;j<p;j++)
            {
                if(Moden[i].value>Moden[j].value)
                   {
                      temp =  Moden[i];
                      Moden[i]=Moden[j];
                      Moden[j]=temp;                           
                   }
            }
    sprintf(Moden[p].moden,"%d/%d.",1,1);
    for(i=0;i<=p;i++)
       {
          strcat(farey,Moden[i].moden);
       }
          
}

3 楼

/*
任意相邻三项 a/b , c/d , e/f 满足(a+e)/(b+f) = c/d。
0/1                                                              1/1
                               1/2
                  1/3                       2/3
         1/4             2/5         3/5               3/4
    1/5      2/7     3/8    3/7   4/7    5/8      5/7         4/5 
递规函数类似二叉树的 中序 输出*/
#include <stdio.h>
#include <string.h>
char *pf;/*全局变量*/
void genfrac(int n,int n1, int d1, int n2, int d2)
{
        if(d1+d2 > n)
            return;/*递规结束*/        
        genfrac(n,n1,d1, n1+n2,d1+d2);
        pf += sprintf(pf,"%d/%d,",n1+n2,d1+d2);
        genfrac(n,n1+n2,d1+d2, n2,d2);
}
void FareySequence(int n, char farey[])
{
     pf = farey;
     pf += sprintf(farey,"%d/%d,",0,1);
     genfrac(n,0,1,1,1);
     sprintf(farey + strlen(farey),"%d/%d",1,1);
}
main()
{
    char a[500];
    int i = 8;
    while(i != 0)
    {
        FareySequence(i, a);
        printf("%s\n",a);
        scanf("%d",&i);
    }
}

4 楼

#include <iostream>
using namespace std;
#include <string>
#include <search.h>
#include <stdlib.h>
void FareySequence(int n, string *farey);
void Print (string *str);
bool Isprime(int a, int b){
   int r = a % b;
   while(r != 0){
       a = b;
       b = r;
       r = a % b;
   }
   return(b == 1);
}
struct fareynode {
    int top;
    int low;
};

int compare (const void  *p,const void  *q) 
{
   return ((struct fareynode*)p)->top * ((struct fareynode*)q)->low - ((struct fareynode*)p)->low *((struct fareynode*)q)->top;
}

int n;
int count=0;
void main()
{
string *farey;
cout<<"请输入n的值:"<<endl;
cin>>n;
farey=new string[n*n];
FareySequence(n,farey);
Print(farey);
}

void FareySequence(int n, string *str)
{fareynode *fareyy;
fareyy=new fareynode[n*n];
char ch[10];
    for(int low = 1; low <= n; ++low){
       for(int top = 0; top <=low; ++top){
           if(Isprime(top,low)){
               fareyy[count].top=top;
               fareyy[count++].low=low;
        
           }
       }
   }

   qsort(fareyy,count, sizeof (struct fareynode), compare);
   for(int i=0;i<count;i++)
   {itoa(fareyy[i].top,ch,10);
    str[i]+=ch;
    str[i]+='/';
    itoa(fareyy[i].low,ch,10);
    str[i]+=ch;}
}
void Print (string *str)
{cout<<"从小到大输出结果为:"<<endl;
    for(int i=0;i<count;i++)
{if(i==i/6*6)
cout<<endl;
cout<<str[i]<<"     ";}
cout<<endl;
}

5 楼

思路就是设A=x1/y1,B=x2/y2,切A<B,则有C=(x1+x2)/(y1+y2),使得A<C<B
因此我设置一个链表(由数组表示),不停加入中间的数,直到分母大于n为止
0/1,                            1/1
0/1,            1/2,            1/1
0/1,    1/3,    1/2,    2/3,    1/1
0/1,1/4,1/3,2/5,1/2,3/5,2/3,3/4,1/1
..........
在VC6.0中编译通过
代码:
---------------------------
/* A node in the Queue*/
struct FareyNum{
    int numerator;
    int denominator;
    int nextIndex; /*pointer to the next number larger than me*/
};

void FareySequence(int n, char farey[]){
    struct FareyNum Q[50];
    int currentIndex=0,tail=1; 
    /* 'tail' indicating where the new number should be add in the array */
    
    /* Initial the Q[0]=0/1  */
    Q[0].numerator=0;
    Q[0].denominator=1;
    Q[0].nextIndex=1;
    /*Initial the Q[1]=1/1  */
    Q[1].numerator=1;
    Q[1].denominator=1;
    Q[1].nextIndex=-1;
    /*while not reach the end of the Queue*/
    while(Q[currentIndex].nextIndex!=-1){
    /* if the denominators's summary of the two nearby numbers is less than n*/                 
    if(Q[currentIndex].denominator+Q[Q[currentIndex].nextIndex].denominator<=n){
        /*Insert a new number between them*/
            Q[++tail].numerator=Q[currentIndex].numerator+Q[Q[currentIndex].nextIndex].numerator;
        Q[tail].denominator=Q[currentIndex].denominator+Q[Q[currentIndex].nextIndex].denominator;
        /*Adjust the next pointer*/
        Q[tail].nextIndex=Q[currentIndex].nextIndex;
            Q[currentIndex].nextIndex=tail;
    }
    /*If the summary of two denominators larger than n, set currentIndex to next number*/
    else currentIndex=Q[currentIndex].nextIndex;
    }/*End while*/
    /*move the number in the Queue into char array*/
    currentIndex=0;
    while(Q[currentIndex].nextIndex!=-1){
    *farey=Q[currentIndex].numerator+'0';
    *(farey+1)='/';
    *(farey+2)=Q[currentIndex].denominator+'0';
    *(farey+3)=',';
    farey+=4;
    currentIndex=Q[currentIndex].nextIndex;
    }
    /* add the last number*/
    *farey=Q[currentIndex].numerator+'0';
    *(farey+1)='/';
    *(farey+2)=Q[currentIndex].denominator+'0';
    *(farey+3)='\0';
}

6 楼

#include<iostream.h>
#include <iomanip.h>
struct xulie
{
    int fzi;
    int fmu;
};
void FareySequence(int n);


void main()
{
    int number;
    cout<<"please input the number:"<<endl;
    cin>>number;
    FareySequence(number);
}
void FareySequence(int n)
{
    int i,j;
    int count=2;
    xulie xl[1000];
    xl[0].fzi=0;
    xl[0].fmu=1;
    xl[1].fzi=1;
    xl[1].fmu=1;
    for(i=n;i>1;i--)
    {
        for(j=1;j<i;j++)
        {
            if((i/j==i)  || (i%j!=0))
            {
                xl[count].fmu=i;
                xl[count].fzi=j;
                count++;
            }
        }
    }
    for(i=0;i<count;i++)
    {
        for(j=0;j<count-i-1;j++)
        {
            if(float(xl[j].fzi)/float(xl[j].fmu)>float(xl[j+1].fzi)/float(xl[j+1].fmu))
            {
                int temp1=xl[j].fzi;
                int temp2=xl[j].fmu;
                xl[j].fzi=xl[j+1].fzi;
                xl[j].fmu=xl[j+1].fmu;
                xl[j+1].fzi=temp1;
                xl[j+1].fmu=temp2;
            }
        }
    }
    for(i=0;i<count;i++)
    {
        cout<<xl[i].fzi<<"/"<<xl[i].fmu<<"   ";
    }

}

7 楼


#include <stdio.h>
#define MAXSIZE     10000
int count = 0;
void FareySequence( int n, char *farey[] )
{
    int i, j;

//    char *farey[MAXSIZE];
    float floatCmp[MAXSIZE];
    char *charTemp;
    float floatTemp;
    for (i = 0; i < n*n/2; i++)
    {
        farey[i] = (char*)malloc(sizeof(char));
    }
    sprintf(farey[0], "0/1");
    for (i = 1; i < n; i++)
    {
        for (j = i+1; j <= n; j++)
        {
            if (0 != j%i || 1 == i)
            {
                count++;
                sprintf(farey[count], "%d/%d", i, j);
                floatCmp[count] = (float)i / (float)j;
            }
        }
    }
    for (i = 0; i <= count; i++)
    {
        for (j = i+1; j <= count; j++)
        {
            if (floatCmp[i] > floatCmp[j])
            {
                floatTemp = floatCmp[i];
                floatCmp[i] = floatCmp[j];
                floatCmp[j] = floatTemp;
                charTemp = farey[i];
                farey[i] = farey[j];
                farey[j] = charTemp;
            }
        }
    }
    sprintf(farey[count+1], "1/1");
}
int main()
{
    int i;
    int n = 100;
    char *farey[MAXSIZE];
    char buf[10];
    FILE *fp = fopen( "result", "w");

    FareySequence(n, farey);

    for (i = 0; i <= count+1; i++)
    {
        sprintf(buf, "%d   ", i);
        fputs(buf, fp);
        fputs(farey[i], fp);
        fputs( "\n", fp );
//        printf("%s\n", farey[i]);
    }
    printf("%d\n", count+2);


    return 0;
}

8 楼

#include<iostream>
#include<cstddef>

using namespace std;


main(){
       int n,i;
      cin>>n;
      double cn=n;
      double* res=new double[n+2];
      res[0]=0;
      res[1]=1/cn;
      cout<<res[0]<<"  "<<res[1]<<"  ";
      for(i=2;i<n+2;i++)if(n%i){
                                res[i]=i/cn;
                                cout<<res[i]<<"  ";
                                }
      res[n+1]=1;
      cout<<res[n+1];
      delete [] res;
      system("pause");
       }

9 楼

呵呵,新人报道,请多关照。简单描述下我的算法,枚举序列中的元素,之后快排,再转字符串,没什么特别的。
    对于Fn的序列,枚举的时间复杂度大约n*n*logn(gcd平均好像是logn?),排序是n*n*logn,数字转字符为n*n,总时间复杂度为O(n*n*logn),空间O(n*n)。
    PS: 有个小问题,farey[]作为参数,空间不用自己分配吧;为了方便测试,main函数也不用自己写吧?第一次参加,不懂规矩,勿怪。


#include<iostream.h>
#include<string.h>
#include<stdlib.h>

double *value;  //记录序列中每个分数的值。分数的比较次数与算法的时间复杂度同级,
                //每次都做除法不划算,所以将它的值保存。
long *order;    //order[i]=j,表示序列中第i个元素是p[j]/q[j]。

int gcd(int a,int b)    //求最大公约数
{
    if (a%b==0) return b;
    return gcd(b,a%b);
}

inline int cp(const void *a,const void *b)  //qsort需要用到的比较函数
{
    if (value[*((long*)a)] > value[*((long*)b)]) 
        return 1;
    return -1;
}

void num2str(int x,char* str)    //数字转字符串
{
    int p=0;
    long t=1;
    while (t*10<=x) 
        t*=10;
    while (t>0) 
    {
        str[p++]=char(x/t+48);
        x%=t;
        t/=10;
    }
    str[p]=0;
}

//字符串连接函数
//开始用的是strcat,时间复杂度达到了惊人的n^4。不得不自己又写了个。
void strJoin(char* a,long* len,const char* b)
{
    int p=0;
    while (b[p])
        a[(*len)++]=b[p++];
    a[*len]=0;
}

void FareySequence(int n, char farey[])
{
    int *p,*q;    //p[]分子,q[]分母
    long maxM=100+n*n/3;    //Fn序列中元素的最大个数。当n比较大时大约是0.30*n*n,所以分配大约0.33*n*n的空间
    long len;        //farey[]的长度
    p=new int[maxM];    
    q=new int[maxM];
    value=new double[maxM];
    order=new long[maxM];

    //枚举所有元素,并一个个加入序列
    long m=0;    //序列中元素个数
    long i,j;
    for (i=2;i<=n;i++)
        for (j=1;j<i;j++)
            if (gcd(i,j)==1)
            {
                p[m]=j;
                q[m]=i;
                value[m]=double(j)/i;
                order[m]=m;
                m++;
            }

    qsort(order,m,sizeof(long),cp);    //快速排序

    //将序列中的元素转换成字符串,存放到farey[]中。
    strcpy(farey,"0/1,");
    len=4;
    for (i=1;i<=m;i++)
    {
        char temp[10];
        num2str(p[order[i-1]],temp);
        strJoin(farey,&len,temp);
        strJoin(farey,&len,"/");
        num2str(q[order[i-1]],temp);
        strJoin(farey,&len,temp);
        strJoin(farey,&len,",");
    }
    strJoin(farey,&len,"1/1");

    delete[] p;
    delete[] q;
    delete[] value;
    delete[] order;
}

10 楼

#include <iostream>
using namespace std;

typedef struct Position {
        double data;    // 数据 
        int index;      // 位置 
}position;

// 求两个数的最大公约数 
int gcd(int m, int n)
{
    int r;
    
    while (n != 0){
          r = m % n;
          m = n;
          n = r;
    }
    return m;
}

// 比较两个双精度小数点的大小 
int cmp(const void *p1, const void *p2)
{
    return *(double *)p1 > *(double *)p2 ? 1 : -1;
}

void FareySequence(int n, char farey[])
{
     char *fareyseq = new char[2 * n * n];
     int index = 0;
     
     // 先求出所有有可能的分数,i为分母,j为分子 
     // 双数保存分子,单数保存分母 
     for (int i = 2; i <= n; i++)
         for (int j = 1; j < i; j++)
             // 利用最大公约数来判断是不是符合要求 
             if (gcd(i, j) == 1)
             {
                fareyseq[2 * index] = j;
                fareyseq[2 * index + 1] = i;
                index++;
             }
     
     position *dptr = new position[index];
     
     // 化为双精度小数 
     for (int i = 0; i < index; i++)
     {
         dptr[i].data = (double)fareyseq[2 * i] /
                   (double)fareyseq[2 * i + 1];
         dptr[i].index = i;
     }
     
     // 按从小到大排列 
     qsort(dptr, index, sizeof(position), cmp);
     
     // 保存序列 
     farey[0] = 0;     // 加上0/1 
     farey[1] = '/';
     farey[2] = 1;
     farey[3] = ',';  
     
     for (int i = 1; i <= index; i++)
     {
         int search = dptr[i - 1].index;
         farey[4 * i] = fareyseq[2 * search];
         farey[4 * i + 1] = '/';
         farey[4 * i + 2] = fareyseq[2 * search + 1];
         farey[4 * i + 3] = ',';
     }
     
     index++;
     farey[4 * index] = 1;   // 加上1/1 
     farey[4 * index + 1] = '/';
     farey[4 * index + 2] = 1;
     
     delete[] fareyseq;
     delete[] dptr;
     return; 
}

我来回复

您尚未登录,请登录后再回复。点此登录或注册