UVa202

刚刚开始写的适合感觉是转换成字符然后开始遍历一遍,后面发现各种不行,就回去看了看题目,重新构思,写了好久还是WA,最后只能看下大神的操作(我太菜了).

先简单梳理下题目意思:首先给出两个数,然后这两个数相除,求相除的结果的“循环节”和“循环节长度”。

一开始没看清楚是循环节,以为是小数点后面的数,然后就WA了。

循环节的意思就是    无限循环小数的 周期的那一段

举个栗子:a/b=3.12345141592614159261415926 14…………分析一下,可以看出这一个无理数的循环周期,拆开看这就是这样的3.12345(1415926)(1415926)(1415926)…………这个数无限在1415926循环,1415926就是它的循环节

回到题目,如果是有限循环小数,那就它的循环节就是0,长度是1。

ok,下面给出代码

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define max 3050
int main()
{
    int n, m;
    int a[3050], b[3050], c[3050];
    while (scanf("%d%d",&n,&m)!=EOF)
    {
        memset(a, 0, sizeof(a));
        memset(b, 0, sizeof(b));
        int len = 0;//小数总长度
        int temp = n;//因为n等下要不断变化成新的被除数,所以先把原始的备份下
        a[len++] = n / m;//a[]是用来保存每一位的商,a[0]用来保存n/m的整数部分
        n = n % m;//n更新成为新的被除数,例如促使n=73,m=25,所以现在n=73%25=23—>n=23,就像我们手写的除法一样

        /*b[]是用来判断每一个被除数是否被除过的,如果同一个被除数被除以两次,那就是无限循环小数了,也就是新的周期的开始
        并且如果n==0的话,那就不是无限循环小数了,也就不用往下计算了*/
        while (!b[n] && n)
        {
            b[n] = len;//标记被除数n是否被除过,并且记录了每一个被除数前面的长度
            c[len] = n;//记录下循环节的起点,后面停止循环后当s[len]==n的时候,那对应的len就是循环节的起点
            a[len++] = n * 10 / m;//上面说了,a[]是用来保存每一位的商,至于为什么乘10呢,这和我们手写除法的时候,下一位加个0是一个道理
            n = n * 10 % m;//n更新为新的被除数
        }
        printf("%d/%d = %d.", temp, m, a[0]);//别忘记小数点了
        for (int i = 1; i < len; i++) {
            if (c[i] == n) { printf("("); }
            printf("%d", a[i]);
        }
        if (n == 0)//如果n==0,也就是该数是有限循环小数
        {
            printf("(0");
        }
        printf(")\n");
        /*这里用了个三目运算符,n是否等于0,如果等于0的话那%d就为1,否则就是len-b[n]
           len是第二个循环节前面的小数的长度,b[n]是第一个循环节前面小数的长度,len-b[n]就是循环节的长度*/
        printf("   %d = number of digits in repeating cycle", !n ? 1 : len - b[n]);
    }
    return 0;
}
全部评论

相关推荐

点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务