六、求循环小数
题目描述
对于任意的真分数 N/M ( 0 < N < M ),均可以求出对应的小数。如果采用链表表示各个小数,对于循环节采用循环链表表示,则所有分数均可以表示为如下链表形式。
输入: N M k
输出: 转换后的小数(不超过 k )
要求: 仅编写将分数转换为小数的函数 change( int n, int m, NODE * head ) 。
预设代码:
/* PRESET CODE BEGIN - NEVER TOUCH CODE BELOW */
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
int data;
struct node * next;
}NODE;
void output( NODE *, int );
void change( int, int, NODE * );
void output( NODE * head, int kk )
{
int k=0;
printf("0.");
while ( head->next != NULL && k<kk )
{ printf("%d", head->next->data );
head = head->next;
k ++;
}
printf("\n");
}
int main()
{
int n, m,k;
NODE * head;
scanf("%d%d%d", &n, &m, &k);
head = (NODE *)malloc( sizeof(NODE) );
head->next = NULL;
head->data = -1;
change( n, m, head );
output( head,k );
return 0;
}
/**************************************
void change(int n, int m, NODE *head)
{
This function is wating for you.
}
***************************************/
/* PRESET CODE END - NEVER TOUCH CODE ABOVE */
测试输入 | 期待的输出 | 时间限制 | 内存限制 | 额外进程 | |
---|---|---|---|---|---|
测试用例 1 | 1 8 50 | 0.125 | 1秒 | 64M | 0 |
测试用例 2 | 29 33 10 | 0.8787878787 | 1秒 | 64M | 0 |
测试用例 3 | 7 18 52 | 0.3888888888888888888888888888888888888888888888888888 | 1秒 | 64M | 0 |
测试用例 4 | 2 7 50 | 0.28571428571428571428571428571428571428571428571428 | 1秒 | 64M | 0 |
解题思路
建立两个数组:商和余数,用来保存结果的商和余数。
让num
每次变为余数的十倍,这样除以m
后的商和余数都是正整数,而不是小数,方便操作。
每次计算完成后都与前面的结果进行比较,如果存在商和余数都相同的情况,那一定存在循环,用 p1
、p2
记录位置,flag
进行标记。如果num
被除尽,则证明没有循环,用 p1
标记最后的位置即可。
根据 p1
的位置构建链表:
- 如果没有循环,则构建的是完整链表;
- 如果
flag
标记有循环,则构建的是前缀,最后根据 p2 的位置补上循环部分即可
因为用到了memset
函数,所以需要补充头文件string.h
上机代码
#include <string.h>
void change(int n, int m, NODE *head )
{
//初始化
int shang[10010], yushu[10010];
memset(shang, 0, sizeof(shang));
memset(yushu, 0, sizeof(yushu));
int p1 = 0, p2 = 0;
int flag = 0;
int num = n * 10;
for (int i = 0; ; i++)
{
shang[i] = num / m;
yushu[i] = num % m;
for (int j = 0; j < i; j++)
{
/* 当商和余数与之前相同时,即标志着出现循环
用p1、p2记录位置,flag=1表示存在循环 */
if(shang[j] == shang[i] && yushu[j] == yushu[i])
{
p1 = j;
p2 = i;
flag = 1;
break;
}
}
num = yushu[i] * 10;
if(!num)//如果num被除尽,变为0,则没有循环
{
p1 = i + 1;
break;
}
if(flag == 1)
{
break;
}
}
/*根据 p1 的位置,如果没有循环,则建立完整链表;
如果有循环,则建立前缀。 */
NODE *r = head;
for (int i = 0; i < p1; i++)
{
//尾插法建立链表
NODE *q = (NODE*)malloc(sizeof(NODE));
q->data = shang[i];
q->next = NULL;
r->next = q;
r = q;
}
//补上循环
if (flag == 1)
{
NODE *r_save = r;
for (int i = p1; i < p2; i++)
{
NODE *q = (NODE*)malloc(sizeof(NODE));
q->data = shang[i];
q->next = NULL;
r->next = q;
r = q;
}
r->next = r_save->next;
}
}