回 帖 发 新 帖 刷新版面

主题:第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个回复)

11 楼

分析:
n=1: 0/1,1/1,
n=2: 0/1,1/2,1/1,
n=3: 0/1,1/3,1/2,2/3,1/1,
n=4: 0/1,1/4,1/3,1/2,2/3,3/4,1/1,
n=5: 0/1,1/5,1/4,1/3,2/5,1/2,3/5,2/3,3/4,4/5,1/1,
规律:
1: 1/2在这组分数的中间位置
2: 从1/2向两边走,每对数相加值为1

注:n=1 不满足以上规律 另行处理

代码:

#include "stdio.h"
#define N 100
/*函数申明*/
int M(int a, int b);/*返回a,b的最大公约数 */
void FareySequence( int n, char farey[] );/*将n级法雷序列存放在数组farey中*/

void main()
{
    char *farey;
    int n, i=0, term;
    printf("输入法雷序列级数:\n");
    scanf("%d", &n);
    FareySequence( n, farey );
    printf("\n");
    while( farey[i] != '\0' )
    { //为了处理 n>=10 时的情况
        if( farey[i] > '9' )
             printf("%d",farey[i]-48);
        else
             printf("%c", farey[i]);
        i++; 
    }
}

void FareySequence( int n, char farey[] )
{
    int a[N], b[N];/*存储分子和分母*/
    int i=1;/*用来计算分数个数*/
    int j, k, count, x, y;
    float z;
    a[0]=0;
    b[0]=1;/*存储第一个分数0/1*/
    for( j=n; j>2; j-- )
        for( k=1; k<=j/2; k++ ) /*只用排列一边的数,另一边可用规律2算出*/
        {
            if( M(j, k) ==1 )/*若a,b互质*/
            {/*将需排列的一边的数存入a[],b[]*/
                a[i]=k;
                b[i]=j;
                i++; 
                
            }
        }
    if( n==1 )
    {
        a[1]=1;    b[1]=1;
    }
    else
    {
        a[i]=1;        b[i]=2;/*存分数1/2*/
        a[2*i]=1;    b[2*i]=1;/*存分数1/1*/
    }
    /*排序*/
    for( j=1; j<i; j++ )
    {/*排0/1与1/2之间的数*/
        x=a[j];    y=b[j];
        z=1.0;
        for( k=j; k<i; k++ )
        {
            if( z > (float)a[k]/b[k] )
            {
                z = (float)a[k]/b[k];
                count = k;
            }
        }
        a[j] = a[count];
        b[j] = b[count];
        a[count] = x;
        b[count] = y;
    }
    /*存入另一边的数*/
    for( k=1; k<i; k++ )
    {/*共有0~2*i, (2*i+1)个数*/        
        a[i+k] = b[i-k] - a[i-k];
        b[i+k] = b[i-k];
    } 
    /*将分数存入farey[]中*/
    for( k=0, j=0; k<=2*i; k++ )
    {
        if( n==1 && k==2 ) break;/*n=1时的不同处理*/
        farey[j++] = a[k]+48;    /*将数字i转换为字符'i'*/
        farey[j++] = '/';
        farey[j++] = b[k]+48;
        farey[j++] = ',';
    }
    farey[j] = '\0'; /*字符串结束符*/
}

int M( int a, int b )
{
    int n, t;
    if( a<b )
    {
        t=a; a=b; b=t;
    }
    while( b!=0 )
    {
        n=a%b;
        a=b;
        b=n;
    }
    return a;
}

测试数据:
10  [enter]
0/1,1/10,1/9,1/8,1/7,1/6,1/5,2/9,1/4,2/7,3/10,1/3,3/8,2/5,3/7,4/9,1/2,5/9,4/7,3/5,5/8,2/3,7/10,5/7,3/4,7/9,4/5,5/6,
6/7,7/8,8/9,9/10,1/1,

12 楼

#include <iostream>
#include <math.h>
using namespace std;

bool pan(int zi, int mu)
{
    int i; 
    int j;
    if(zi>1&&mu%zi==0)
        return false;
    j = (int)sqrt((float)zi);
    if(zi % 2 == 0) //先判断2
        if(mu % 2 == 0)
            return false;
    for(i = 3; i <= j;i+=2) //然后判断所有奇数
        if(zi % i == 0)
            if(mu % i == 0)
                return false;
    return true;
}

void FareySequence(int n, char farey[])
{
    int zi,mu;
    zi = 1;
    mu = n;
    int len = 0;
    int count = 0;
    double *a;
    char **b;

    while(1)
    {
        if(zi<mu)
            if(pan(zi,mu))
                len++;
        if(mu > 2)
            mu--;
        else
        {
            mu = n;
            zi++;
        }
        if(zi == n)
            break;
    }

    zi = 1;
    mu = n;

    a = new double[len];
    b = new char*[len];
    for(int i = 0; i < len; i++)
        b[i] = new char[4];

    while(1)
    {
        if(zi<mu)
            if(pan(zi,mu))
            {
            a[count] = (double)zi/mu;
            b[count][0] = zi+48;
            b[count][1] = '/';
            b[count][2] = mu+48;
            b[count][3] = '\0';
            count++;
            }
        if(mu > 1)
            mu--;
        else
        {
            mu = n;
            zi++;
        }
        if(zi == n)
            break;
    }

    for(int i = 0; i < len-1; i++)
        for(int j = i+1; j < len; j++)
            if(a[i] > a[j])
            {
                double temp = a[i];
                a[i] = a[j];
                a[j] = temp;
                char p[4];
                strcpy(p,b[i]);
                strcpy(b[i],b[j]);
                strcpy(b[j],p);
            }

    farey[0] = '0';
    farey[1] = '/';
    farey[2] = '1';
    farey[3] = ',';
    for(int i = 0; i < len; i++)
    {
        farey[4+i*4] = b[i][0];
        farey[5+i*4] = b[i][1];
        farey[6+i*4] = b[i][2];
        farey[7+i*4] = ',';
    }
    farey[4+len*4] = '1';
    farey[5+len*4] = '/';
    farey[6+len*4] = '1';
    farey[7+len*4] = '\0';
    
    delete[]a;
    delete[]b;

    return;
}

int main(void)
{
    char farey[92];
    int n = 8;
    FareySequence(n,farey);
    cout << farey << endl;
    cin.get();
    return 0;
}

13 楼

// 36match1.cpp : Defines the entry point for the console application.
//
//#define  REAL_TIME_CALC
//#define OUT_TIME

//#include "stdafx.h"

#ifdef OUT_TIME
    #include "currTime.h"    
#endif
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <memory.h>
#include <string.h>
#include <stdlib.h>
#include <search.h>

typedef  unsigned char BYTE;
typedef  unsigned long DWORD;
typedef  unsigned short WORD;
typedef  int           BOOL;

#define  TRUE    1
#define  FALSE   0

#define FAREY_BASE          1000
#define FRACTION_ARRAY_BASE 64

typedef struct _PrimeTab
{
    DWORD *PrimeTab;
    BYTE *byteFlag;
    int   max;
    int   count;
}PrimeTab;

typedef struct _Fraction
{
#ifndef REAL_TIME_CALC
     double value;
#endif
    WORD  numerator;
    WORD  denominator;
}Fraction;


typedef struct _FractionArray
{
    Fraction *Data;
    int size;
    int count;
}FractionArray;
    
typedef struct _FareyArray
{
    BYTE *pByteArray;
    int   byteArrayLen;
    int   fac_count;
    DWORD fac[32];
    FractionArray array;
}FareyArray;


// 全局变量,质数表
PrimeTab g_primeTab=
{
    NULL,
    NULL,
    0,
    0
};

FareyArray g_fareyArray;

//将n转化为字符串str,不写入字符串结束符0
//如果不考虑性能,可用sprintf(str,"%d",n)来实现类似的功能
char* my_itoa(int n,char *str)
{
    char buff[12];
    char *p=buff+11;
    if (n==0)
    {
        *str++='0';
        return str;
    }
    *p--=0;
    while (n>0)
    {
        *p-- = (n % 10)+'0';
        n/=10;
    }
    p++;
    while (*p)
        *str++= *p++;
    return str;
}

//扩大动态数组的存储空间
//形如FractionArray_实现动态数组的部分功能
//在C++中,可以用直接使用 STL中的 vector
BOOL FractionArray_setSize(FractionArray *me,int newSize)
{
    if  ( newSize < me->size || newSize==me->size)
        return FALSE;

    Fraction *p=new Fraction[newSize];
    
    if (p==NULL)
        return FALSE;
    //--------------------
    if ( me->Data!=NULL)
    {
        memcpy(p,me->Data,sizeof(Fraction)*me->size);
        delete[] me->Data;
    }
    
    me->Data=p;
    me->size=newSize;
    return TRUE;
}

//形如FractionArray_实现动态数组的部分功能
//在C++中,可以用直接使用 STL中的 vector
//将n添加到动态数组中
BOOL FractionArray_Append(FractionArray *me,Fraction n)
{
    BOOL bRet=TRUE;

    if ( me->count == me->size)
    {
        int newSize= (me->size + me->size/4+256-1) >> 8;
        newSize <<=8 ;
         
        bRet=FractionArray_setSize(me,newSize);
    }
    
    if (!bRet)
    {
        printf("No enough memory\n");
        return bRet;
    }
    me->Data[me->count]=n;
    me->count++;
    return TRUE;
}


static int __cdecl FractionCompare(const void *element1,const void *element2)
{
    Fraction *p1,*p2;
    p1=(Fraction *)element1;
    p2=(Fraction *)element2;

#ifdef REAL_TIME_CALC
    double v1,v2;
    v1=(double)(p1->numerator) / (double)(p1->denominator);
    v2=(double)(p2->numerator) / (double)(p2->denominator);
    if ( v1 > v2)
        return 1;
    else  if ( v1 < v2 )
        return -1;
    else 
        return 0;
#else
    if ( (p1->value) > (p2->value))
        return 1;
    else  if ( (p1->value) < (p2->value))
        return -1;
    else 
        return 0;
#endif
}

//使用c库函数qsort(快速排序对分数数组排序)
void FractionArray_Sort(FractionArray *me)
{
     qsort( me->Data, (size_t)me->count, sizeof( Fraction), FractionCompare );
}

//输出分数数组的所有分数到buff,各个分数用/来隔开
void FractionArray_output(FractionArray *me,char buff[] )
{
    int i;
    char *tag;
    
    for (tag=buff,i=0;i<me->count-1;i++)
    {
        tag=my_itoa( me->Data[i].numerator,tag);
        *tag++='/';
        tag=my_itoa( me->Data[i].denominator,tag);
        *tag++=',';
    }
    
    i=me->count-1;
    tag=my_itoa( me->Data[i].numerator,tag);
    *tag++='/';
    tag=my_itoa( me->Data[i].denominator,tag);
    *tag=0;
}

//形如FractionArray_实现动态数组的部分功能
//在C++中,可以用直接使用 STL中的 vector
//释放分数数组所占用的内存空间
void FractionArray_Free(FractionArray *me)
{
    if (me->Data!=NULL)
        delete[] me->Data;
    me->Data=NULL;
    me->count=0;
    me->size=0;
}

//形如FractionArray_实现动态数组的部分功能
//在C++中,可以用直接使用 STL中的 vector
//初始化分数数组,预留FRACTION_ARRAY_BASE个元素空间
void FractionArray_Init(FractionArray *me)
{
    me->Data=NULL;
    me->count=0;
    me->size=0;
    FractionArray_setSize(me,FRACTION_ARRAY_BASE);
}

14 楼

//接上页

// 用埃氏筛法计算n以内的所有质数
//sift the all prime less than  n 
void PrimeTab_Sift(BYTE *siftbuff,DWORD n)
{
    DWORD i,sqrt_n,p;
    //----------------------------
    sqrt_n=(int)sqrt(n)+1;
    while (sqrt_n*sqrt_n >n)
        sqrt_n--;
    
    memset(siftbuff,1,n+1);

    *siftbuff=0;
    *(siftbuff+1)=0; //1不是质数
    *(siftbuff+2)=1; //2是质数

    for (i=4;i<=n;i+=2)
        *(siftbuff+i)=0;          //筛去2的倍数

    for (i=3;i<=sqrt_n;) //i 是质数
    {
        for (p=i*i;p<=n; p+=2*i)
            *(siftbuff+p)=0; //筛去i 的奇数倍
        i+=2;
        while ( *(siftbuff+i)==0 ) 
            i++; //前进到下一个质数
    }
}

//初始化n以内的质数表,
//如果质数的范围小于n,则用埃氏筛法重新筛选质数
BOOL PrimeTab_ReSift(PrimeTab *pTab,DWORD n)
{
    int i,count1,count2;
    if ( n<=pTab->max)
        return TRUE;

    if (pTab->byteFlag!=NULL)
    {
        delete[] pTab->byteFlag;
        pTab->byteFlag=NULL;
    }      
    
    if (pTab->PrimeTab!=NULL)
    {
        delete[] pTab->PrimeTab;
        pTab->PrimeTab;
    }

    pTab->byteFlag=new BYTE[n+1];
    if (pTab->byteFlag==NULL)
        return FALSE;
    
    PrimeTab_Sift(pTab->byteFlag,n);
    
    //统计n以内的所有质数的个数
    for (count1=0,i=0;i<=n;i++)
    {
        if (pTab->byteFlag[i])
            count1++;
    }
    
    pTab->PrimeTab=new DWORD[count1];
    
    //将筛出来的质数放入质数表
    count2=0;
    for (i=0;i<=n;i++)
    {
        if (pTab->byteFlag[i])
        {
            pTab->PrimeTab[count2]=i;
            count2++;
        }
    }
    pTab->max=n;
    pTab->count=count2;
    return TRUE;
}


//释放FareyArray变量占用的内存空间
BOOL Farey_Free(FareyArray *p)
{
    if (p->pByteArray!=NULL)
    {
        delete[] p->pByteArray;
        p->pByteArray=NULL;
    }
    p->byteArrayLen=0;
    FractionArray_Free(&(p->array));
    return TRUE;
}

//为本程序分配所需的内存空间,仅需在main开始时调用一次
BOOL InitData()
{
    g_fareyArray.byteArrayLen=0;
    g_fareyArray.pByteArray= new BYTE[FAREY_BASE+1];
    if (g_fareyArray.pByteArray==NULL)
        return FALSE;
    
    g_fareyArray.byteArrayLen=FAREY_BASE;
    FractionArray_Init( &(g_fareyArray.array));
    return TRUE;
}

//释入为本程序分配所需的内存空间,仅需在main结束时时调用一次
void FreeData()
{
    if (g_primeTab.PrimeTab!=NULL)
        delete[] g_primeTab.PrimeTab;
    
    if (g_primeTab.byteFlag!=NULL)
        delete[] g_primeTab.byteFlag;

    g_primeTab.count=0;
    g_primeTab.max =0;
    
    g_primeTab.PrimeTab=NULL;
    g_primeTab.byteFlag=NULL;

    Farey_Free(&g_fareyArray);
}

//为计算法雷序列分配内存空间 
BOOL Farey_Init(FareyArray *p,int n)
{
    if (n< p->byteArrayLen  && p->pByteArray!=NULL) 
        return TRUE;

    p->byteArrayLen=0;
    p->pByteArray= new BYTE[n+1];
    if (p->pByteArray==NULL)
        return FALSE;
    
    p->byteArrayLen=n;
    FractionArray_Init( &(p->array));
    return TRUE;
}

// 判断n 是否是质数,是返回1,否,将素因子存入p->fac
int Farey_isPrime( int n,
    FareyArray *p,
    PrimeTab *primeTab
    )
{
    int flag,t,i=0;

    p->fac_count=p->fac[0]=0;
    
    if ( primeTab->byteFlag[n] )
        return TRUE;

    i=0;
    while (n>1 && i<primeTab->count)
    {
        t=primeTab->PrimeTab[i];
        if ( t*2>n)
            break;

        flag=0;
        while ( n % t==0 )
        {
            n /=t;
            flag=1;
        }

        if ( flag)
        {
            p->fac[p->fac_count]=t;
            p->fac_count++;
        }
        
        if ( primeTab->byteFlag[n] )
        {
            p->fac[p->fac_count]=n;
            p->fac_count++;
            break;    
        }
        i++;
    }
    return FALSE;
}

15 楼


//将分母为n的最简分数,添加到数组pFareyArray中去
BOOL AddToFractionArray(int n,FareyArray *pFareyArray,PrimeTab *pPrimeTab)
{
    BOOL bIsPrime,bRet;
    int j,j1,j2,t;
    Fraction  frac;
    
    bIsPrime=Farey_isPrime(n,pFareyArray,pPrimeTab);
    if ( bIsPrime)
    {
        for (j=1;j<n;j++)
        {
            frac.numerator=j;
            frac.denominator=n;
#ifndef REAL_TIME_CALC
            frac.value= (double)frac.numerator / (double)frac.denominator;
#endif
            bRet=FractionArray_Append(&(g_fareyArray.array),frac);
            if (!bRet)
                return bRet;
        }
    }
    else
    {
        memset( g_fareyArray.pByteArray,0,g_fareyArray.byteArrayLen);
        //筛去和分母不互质的所有分子
        for (j1=0;j1<g_fareyArray.fac_count;j1++)
        {
            t=g_fareyArray.fac[j1];
            for (j2=t;j2<n;j2+=t)
                g_fareyArray.pByteArray[j2]=1;
        }
        
        for (j1=1;j1<n;j1++)
        {
            //仅仅将和n(分母)互质的数组成的分数添加到分数数组
            if (g_fareyArray.pByteArray[j1]==0)
            {
                frac.numerator=j1;
                frac.denominator=n;
#ifndef REAL_TIME_CALC
                frac.value= (double)frac.numerator / (double)frac.denominator;
#endif
                bRet=FractionArray_Append(&(g_fareyArray.array),frac);
                if (!bRet)
                    return bRet;
            }
        }

    }
    return TRUE;
}

//按照比赛要求编写的函数,首次调用时FareySequence,需调用InitData,
//再次调用时,不需要调用InitData,参见测试函数main
//对n没有算法上的限制,实际上对n的主要限制来自主存容量,

//在调用这个函数时,需要分配一块内存用于存储字符串,这需要很大的内存空间,
//根据我的测试经验,大概需n*n*3 字节,我的测试程序中,这个值取n*n*4,
//当n较小时,(在我的计算机,内存256M,n<4000左右时),不需要虚拟内存,速度很快,
//当n更大时,(在我的计算机,n>5000左右),则使用虚拟内存,速度变慢
//当n大于一定程度(在我的计算机上,n=7000 可工作,更大的n没有测试),虚拟内存也会不足,
//则这个函数不能工作
    
void FareySequence(int n,char farey[])
{
    int i,sqrt_n;
    double t1,t2,t3;
    Fraction  frac;
    BOOL bRet;
    //----------------------------------
    
    farey[0]=0;
    bRet=PrimeTab_ReSift(&g_primeTab,n);
    if (!bRet)
        return;
    
    if (!Farey_Init(&g_fareyArray,n))
        return ;

    #ifdef OUT_TIME
    t1=currTime();
    #endif
    for (i=2;i<=n;i++)
    {
        //printf("i=%d\n",i);
        bRet=AddToFractionArray(i,&g_fareyArray,&g_primeTab);
        if (!bRet)
            return;
    }
    #ifdef OUT_TIME
    t1=currTime()-t1;
    #endif
    
    frac.numerator=0;
    frac.denominator=1;
#ifndef REAL_TIME_CALC
    frac.value= 0.00;
#endif
    FractionArray_Append(&(g_fareyArray.array),frac);
    
    frac.numerator=1;
    frac.denominator=1;
#ifndef REAL_TIME_CALC
    frac.value= 1.00;
#endif
    FractionArray_Append(&(g_fareyArray.array),frac);

    #ifdef OUT_TIME
    t2=currTime();
    #endif
    FractionArray_Sort(&(g_fareyArray.array));
    #ifdef OUT_TIME
    t2=currTime()-t2;
    t3=currTime();
    #endif

    FractionArray_output(&(g_fareyArray.array),farey);
    #ifdef OUT_TIME
    t3=currTime()-t3;
    #endif

    FractionArray_Free(&(g_fareyArray.array));
    FractionArray_Init(&(g_fareyArray.array));
    #ifdef OUT_TIME
    printf("calc time=%.12f s\nSort time=%.12f s\noutput time=%.12f s\n",t1,t2,t3);
    #endif
}

int main(int argc, char* argv[])
{
    
    int n;
    char *pBuff=NULL;
    char name[32]; 
    FILE *fp=NULL;

    InitData();

    while (1)
    {
        printf("n=?");
        scanf("%d",&n);
        if (n==0)
            break;
        pBuff=new char[n*n*4+4096];
        if (pBuff==NULL)
            return 0;
        FareySequence(n,pBuff);
        sprintf(name,"%d.txt",n);
        
        fp=fopen(name,"wt");
        fwrite(pBuff,1,strlen(pBuff),fp);
        fclose(fp);    
        delete[] pBuff;
    }

    FreeData();
    return 0;
}
//测试表明,qsort函数是瓶颈,我将提交另一个程序,再次提高速度。

16 楼

void FareySequence(int n,char farey[]){
     #define NULL 0
     struct fs{
            int a,b;
            struct fs *next;
            };
     struct fs *fs_start,*fs_end,*p,*l,*r,*m;
     int i,size;
     size=sizeof(struct fs);
     fs_start=(struct fs *)malloc(size);
     fs_end=(struct fs *)malloc(size);
     fs_start->a=0;
     fs_start->b=1;
     fs_start->next=fs_end;
     fs_end->a=1;
     fs_end->b=1;
     fs_end->next=NULL;
     for(i=1;i<n;i++){
       l=fs_start;
       r=l->next;
        do{
          if ((l->a+r->a)<n&&(l->b+r->b)<=n){
               m=(struct fs *)malloc(size);
               m->a=l->a+r->a;
               m->b=l->b+r->b;
               m->next=r;
               l->next=m;
            }
          l=r;
          r=r->next;
        }while(r!=NULL);
     }
     
     m=fs_start;
     i=0;
     do{
          farey[i++]=m->a+48;
          farey[i++]='/';
          farey[i++]=m->b+48;
          farey[i++]=',';
          m=m->next;   
     }while(m->next!=NULL);
     farey[i++]=m->a+48;
     farey[i++]='/';
     farey[i++]=m->b+48;
}

如果n大于9我就没有好的办法把他们放到数组中了。

17 楼


kan kan

18 楼

看看大家怎么写

19 楼

看看。。。。

20 楼

偶是第一次来参加,所以准备了好久,写了又写,改了又改,换了好几个版本了,现在终于定稿了,有不合规则的地方请多包含。
    先说一下我的思路,我是用结构体表示分数,然后用链表来储存生成的法雷序列。法雷序列存在性质:对任意三项a/b,c/d,e/f有(a+e)/(b+f)=c/d(这个规律从网上搜出来的,不犯规吧?),所以我先给出第一项0/1和最后一项1/1,然后用此性质来生成中间的项。先用前两项生成他们中间一项,再用新的前两项继续生成他们中间的项,直到生成的分数化为最简后分母大于n,则说明这两项间没有其他项了,用第2、3项继续生成,实际操作中为节省内存,我就把第一项(头结点)存盘,第2、3项又变为前两项,以此类推,最终只剩一项,则完成。把最后一项也存盘,根据统计出的法雷序列的字节数来为farey分配内存(大于最大整数32627则作失败处理)。
    因为题目中函数原型为void FareySequence(int n, char farey[]);,只能对farey[]赋值但不能给它分配内存,也就是farey[]应在调用函数前分配内存,可是n不同时其占用的字节数变化很大,又无法用n估算其会占多少内存,所以我是在函数中求出法雷序列大小来后再分配内存的,为了这样,我把函数原型改成了
void FareySequence(int n, char **farey); ,不妥之处,请多多原谅。
我是在WinXP,Dev-C++下编译通过的,当n较大时执行时间会很长,我最大输入10000试了试,几分钟后才搞定,统计出分数个数为30397487个,保存序列的文件280多MB...

说了一大堆废话了,下面是我的程序:

#include <stdio.h>
#include <stdlib.h>
#define fenshu struct fs
#define MINN 1       /* n的最小值 */
#define MAXN 10000   /* n的最大值 */
fenshu       /*表示分数的结构体 */
 {int fenzi,fenmu;  /*fenzi--分子 ,fenmu--分母*/ 
  fenshu *next;
 };
void huajian(int *fz,int *fm);   /*将分数化为最简分数,fz为分子,fm为分母 */ 
void addnode(int nodesize,fenshu **place,int fz,int fm,long *nodenum);   /*在指定位置后添加一个结点 */
void puthead(fenshu **head,FILE *fp, long *len);  /*将头结点写入文件以释放内存空间 */
void FareySequence(int n, char **farey);  /*产生法雷序列 */ 

int main()
{int n;
 char *farey;
 printf("Pleas input n:");
 scanf("%d",&n);
 if (!(n >= MINN && n <= MAXN))
   {printf("Input error!\n");  system("pause");  exit(1);}
 FareySequence(n,&farey);
 if (farey!=NULL)
   printf("F%d=\"%s\"\n",n,farey);
 system("pause");
 return 0;
}

void huajian(int *fz,int *fm)   /*将分数化为最简分数,fz为分子,fm为分母 */ 
{int i,j,r;
 i=*fm;  j=*fz;
 r=i%j;
 while (r!=0)
   {i=j;  j=r;  r=i%j; }
 *fm/=j;   *fz/=j;
}
void addnode(int nodesize,fenshu **place,int fz,int fm,long *nodenum)   /*在指定位置后添加一个结点 */ 
{fenshu *p;         
 p=(fenshu *)malloc(nodesize);
 p->fenzi=fz;  p->fenmu=fm;  p->next=(*place)->next;
 (*place)->next=p;
 (*nodenum)++;
}
void puthead(fenshu **head,FILE *fp, long *len)  /*将头结点写入文件以释放内存空间 */
{fenshu *p;
 p=*head;   /* 保存原来结点 */
 *len+=fprintf(fp,"%d/%d,",p->fenzi,p->fenmu); /*  写盘 */
 *head=p->next;  /*头结点后移 */
 free(p);        /* 释放原来结点 */
}
void FareySequence(int n, char **farey)    /*产生法雷序列 */ 
{fenshu *head,*p;
 int i,nodesize,fz,fm;
 long len=0L,nodenum;
 FILE *fp;
 if((fp=fopen("farey.txt","w"))==NULL)
   {printf("file can't open.\n"); exit(1); }  
 nodesize=sizeof(fenshu);
 p=(fenshu *)malloc(nodesize);   /*建立第一个结点 0/1 */ 
 p->fenzi=0;  p->fenmu=1;  p->next=NULL;
 head=p;   nodenum=1L;
 addnode(nodesize,&head,1,1,&nodenum);   /*在链表后加上1/1,第二个结点*/    
 p=head->next;   /*控制head,p始终指向链表最开始2个结点 */ 
 /* 初始化完成,准备通过法雷序列的性质往链表中添加结点 */ 
 while (NULL != p) /* p为空时head已是最后一个结点,添加结束 */ 
  {fz=head->fenzi + p->fenzi;
   fm=head->fenmu + p->fenmu;
   huajian(&fz,&fm);
   if (fm > n)  /*计算出的分母大于n说明head,p间已不存在n级法雷序列的分数*/ 
     puthead(&head,fp,&len);  /*将头结点写入文件以释放内存空间 */      
   else   /*否则将该分数添加到head与p之间*/ 
     addnode(nodesize,&head,fz,fm,&nodenum);   
   p=head->next;    /*较对p的位置*/ 
  }
 len+=fprintf(fp,"%d/%d",head->fenzi,head->fenmu);  /*将最后一个结点写入文件 */ 
 fclose(fp);
 /*将法雷序列从文件读入farey中 */ 
 printf("nodenum=%ld, len=%ld\n",nodenum,len);
 if (len > 32626) /*若字节数超出整形范围(32626+'\0'即32627) */ 
   {printf("string too long !"); goto fail; }   
 if (NULL==(*farey=(char *)malloc(len+1)))
   {printf("momory not enough !"); goto fail; }
 *(*farey+len)='\0';
 if (NULL==(fp=fopen("farey.txt","rb")))
   {printf("file can't open !"); goto fail; }
 if (fread(*farey,1,len,fp)!=len)
   {printf("file read error!");  goto fail; }
 fclose(fp);
 printf("Successful ! \n");
 return;
fail: 
 *farey=NULL; printf("Failed !\nresult saved in\"farey.txt\".\n");
 return;
}

我来回复

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