主题:第36次编程比赛第1题题目
boxertony [专家分:23030] 发布于 2006-08-04 12:24:00
法雷序列:
对任意给定的一个自然数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个回复)
沙发
ITER [专家分:680] 发布于 2006-08-04 15:16:00
/*************
写了个可能效率比较低的 呵呵
还要麻烦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]
板凳
joekings [专家分:550] 发布于 2006-08-04 16:16:00
#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 楼
ccpp [专家分:9360] 发布于 2006-08-04 22:40:00
/*
任意相邻三项 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 楼
liyanguestc [专家分:90] 发布于 2006-08-04 23:57:00
#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 楼
gz80 [专家分:0] 发布于 2006-08-05 01:13:00
思路就是设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 楼
asddg67 [专家分:1580] 发布于 2006-08-05 01:21:00
#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 楼
bloodybg [专家分:1510] 发布于 2006-08-05 10:35:00
#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 楼
magicalking [专家分:150] 发布于 2006-08-05 10:58:00
#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 楼
neverPE [专家分:1620] 发布于 2006-08-05 12:02:00
呵呵,新人报道,请多关照。简单描述下我的算法,枚举序列中的元素,之后快排,再转字符串,没什么特别的。
对于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 楼
czarwind [专家分:0] 发布于 2006-08-05 15:00:00
#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;
}
我来回复