UVa202
Posted caibingxu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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是否等于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; }
以上是关于UVa202的主要内容,如果未能解决你的问题,请参考以下文章
[算法竞赛入门经典]Repeating Decimals, ACM/ICPC World Finals 1990,UVa202