一:题目

  1. 输入整数ab(<=a<=,<=b<=),输出a/b的循环小数表示以及循环节长度。
  2.  
  3. 例如,a=,b=,小数表示为0.(),循环字节长度为21

  1. 当循环节长度超过50时,后面使用...代替,不进行输出后面部分

(一)样例输入

  1.  

(二)样例输出

  1. / = 3.04()
  2.    = number of digits in repeating cycle
  3. / = .()
  4.    = number of digits in repeating cycle
  5. / = .(...)
  6.    = number of digits in repeating cycle

二:题目分析

(一)余数用作判断循环节的依据:(循环节长度大小不会超过余数大小,原因如下:)

  1. /-->/=...
  2. /-->/=...4出现两次4,所以一定会出现循环节
  3. /-->/=...4出现三次4,所以循环节就在二三次之间(即商6
  1. 所以用一个数组记录余数,大小不会超过除数大小

(二)同时也要记录商,用于记录循环节

  1. 若是除数为P,则余数为0->P-1;所以在P次之间一定会出现两个相同余数  //(一中原因)
  1. -->一定会出现循环节
  1. 所以我们再记录一次余数,当出现某个余数出现为3次,那么循环节在两个余数位置中间
  2. 由于商数组和余数数组对应,所以可以轻松找到循环节

(三)商数组和余数数组大小

  1. 余数数组大小应该为除数大小  //余数只需要除数大小,用于记录余数出现次数
  2. 商数组大小应该为除数大小的两倍  //商用于记录对应余数中的商值,由于每一个余数必须出现3次,所以我们记录的商必须足够长,足以支持余数次数到达3

例:

  1. 其中0<=a<=,<=b<=--->
  2. 所以余数数组不会超过3000 商数组大小不超过6000

注:上面的商和余数数组只记录小数点后的值,不记录整数值

三:代码分析(使用76/25 ,1/6 ,5/43分析)

(一)处理整数部分:只剩下会出现小数部分的被除数进行下一步处理

  1. //开始处理数据
  2. //1.获取整数
  3. //先记录整数:可以在记录时直接输出,节省篇幅
  4. printf("%d/%d = ", a, b);
  5. if (!(a / b))
  6. printf("");
  7. else
  8. while (a / b)
  9. {
  10. printf("%d", a / b);
  11. a %= b;
  12. }
  13. printf(".");

(1)76/25

  1. /=...
  1. 代码输出76/25 = 3.

(2)1/6

  1. 直接为小数,所以按照代码输出1/6 = 0.

(3)5/43

  1. 直接为小数,所以按照代码输出5/43 = 0.

(二)获取商数组和余数数组

  1. //2.开始记录商和余数
  2. i = ;
  3. while () //例如:1/6
  4. {
  5. //记录商和余数
  6. res[i] = a * 10 / b; //10/6=1            //1.记录商
  7. rem[a * 10 % b]++; //10%6=4          //2.记录对应余数位置出现次数
  8. //注意两次和三次都是只记录一次即可
  9. if (rem[a * 10 % b] == 2&&!two_flag) //3.若是出现两次,则开始进行记录  只记录第一个出现两次的余数
  10. {
  11. r_s = i;
  12. two_flag = ;
  13. }
  14. if (rem[a * 10 % b] == 3)          //4.若是出现3次,则确定了循环节位置,直接跳出
  15. {
  16. r_e = i;
  17. break;
  18. }
  19. //处理被除数
  20. a = a * % b; //a = 4
  21. i++;
  22. }

(1)76/25

  1. /=... 0  1  第一个为商下标,第二个为余数次数
  2. /=... 1  1  
  3. /=... 2  2  余数出现两次时的商0和出现一次时的商4不一致
  4. /=... 3  3
  1. res = { }
  2. rem = { }

(2)1/6

  1. /=... 0  1  第一个为商下标,第二个为余数次数
  2. /=... 1  2  余数出现两次时的商6和出现一次时的商1不一致
  3. /=... 2  3
  1. res = { }
  2. rem = { }

(3)5/43

  1. /=... 0     1
  2. /=...
  3.  
  4. ...
  5. .....=... 21    2  余数出现两次时的商和出现一次时的商一致
  6.  
  7. ...
  8. .....=... 42    3

(三):进行数据输出

  1. 注意记录数据时要区分0.() 3.04() 0.(....)
  2. 不同之处在于循环节是不是从小数第一位开始
  3. 处理原则在于看12两次余数相同时,商是否一致(上面案例)
  1. int rep_count = r_s;
  2. if (res[r_s] != res[2 * r_s - r_e])  //若是余数第一次和第二次对应的商值不一样,则加一
  3. rep_count++;
  4. for (j = ; j <rep_count ;j++) //注意,先看下面注释,可以知道,真正循环节结束在我们获取的第二个相同余数位置-->即r_s
  5. {
  6. if (j == * r_s - r_e && rep_count==r_s) //注意这里:不是j-r_s
  7. printf("(");
  8. else if (j == * r_s - r_e+&&rep_count==r_s+) //遇到循环节不是从小数点后开始,则向后一位
  9. printf("(");
  10. printf("%d", res[j]);
  11. if (j +r_e- *r_s == ) //不是j-r_s -->因为我们虽然确定r_s到r_e时一个循环节,但是r_s是第二个相同余数开始,r_e是第三个余数开始
  12. { //4 4 4--->r_s是第二个开始,r_e是第三个开始,但是真的循环节是从第一个4到第二个4
  13. printf("...");
  14. break;
  15. }
  16. }
  17.  
  18. printf(")\n");
  19. printf(" %d = number of digits in repeating cycle\n", r_e - r_s);

四:代码实现

  1. void test33()
  2. {
  3. int a, b;
  4. int zs[]; //存放整数,例如结果10.13161616,这里用于存放10
  5. //由于程序变更,后面没有用到zs,但是为了便于理解,留在这
  6. int res[MAX_REP]; //存放商
  7. int rem[MAX_REP]; //存放余数
  8.  
  9. int two_flag; //注意两次和三次都是只记录一次即可,但是由于三次直接break,所以不做标志
  10.  
  11. int i, j;
  12. int r_s, r_e; //循环节开始,循环节结束
  13.  
  14. FILE* fi = freopen("data2.in", "r", stdin);
  15. freopen("data2.out", "w", stdout);
  16.  
  17. while (!feof(fi))
  18. {
  19. scanf("%d", &a);
  20. scanf("%d", &b);
  21.  
  22. memset(zs, , sizeof(zs));
  23. memset(res, , sizeof(res));
  24. memset(rem, , sizeof(rem));
  25.  
  26. two_flag = ;
  27.  
  28. //开始处理数据
  29. //1.获取整数
  30. //先记录整数:可以在记录时直接输出,节省篇幅
  31. printf("%d/%d = ", a, b);
  32. if (!(a / b))
  33. printf("");
  34. else
  35. while (a / b)
  36. {
  37. printf("%d", a / b);
  38. a %= b;
  39. }
  40. printf(".");
  41.  
  42. //2.开始记录商和余数
  43. i = ;
  44. while () //例如:1/6
  45. {
  46. //记录商和余数
  47. res[i] = a * / b; //10/6=1
  48. rem[a * % b]++; //10%6=4
  49.  
  50. //注意两次和三次都是只记录一次即可
  51. if (rem[a * % b] == &&!two_flag) //若是出现两次,则开始进行记录
  52. {
  53. r_s = i;
  54. two_flag = ;
  55. }
  56. if (rem[a * % b] == )
  57. {
  58. r_e = i;
  59. break;
  60. }
  61. //处理被除数
  62. a = a * % b; //a = 4
  63. i++;
  64. }
  65.  
  66. //开始记录数据
  67. //注意记录数据时要区分0.1(6) 3.04(0) 和0.(11....)
  68. //不同之处在于循环节是不是从小数第一位开始
  69. //处理原则在于看1,2两次余数相同时,商是否一致
  70. int rep_count = r_s;
  71. if (res[r_s] != res[ * r_s - r_e])
  72. rep_count++;
  73.  
  74. for (j = ; j <rep_count ;j++) //注意,先看下面注释,可以知道,真正循环节结束在我们获取的第二个相同余数位置-->即r_s
  75. {
  76. if (j == * r_s - r_e && rep_count==r_s) //注意这里:不是j-r_s
  77. printf("(");
  78. else if (j == * r_s - r_e+&&rep_count==r_s+) //遇到循环节不是从小数点后开始,则向后一位
  79. printf("(");
  80. printf("%d", res[j]);
  81. if (j +r_e- *r_s == ) //不是j-r_s -->因为我们虽然确定r_s到r_e时一个循环节,但是r_s是第二个相同余数开始,r_e是第三个余数开始
  82. { //4 4 4--->r_s是第二个开始,r_e是第三个开始,但是真的循环节是从第一个4到第二个4
  83. printf("...");
  84. break;
  85. }
  86. }
  87.  
  88. printf(")\n");
  89. printf(" %d = number of digits in repeating cycle\n", r_e - r_s);
  90. }
  91.  
  92. freopen("CON", "r", stdin);
  93. freopen("CON", "w", stdout);
  94. }

算法习题---3.08循环小数(UVa202)的更多相关文章

  1. 【算法习题】数组中任意2个(3个)数的和为sum的组合

    题1.给定一个int数组,一个数sum,求数组中和为sum的任意2个数的组合 @Test public void test_find2() { int[] arr = { -1, 0, 2, 3, 4 ...

  2. 循环小数 UVa202

    输入整数a和b(0<=a<=3000,1<=b<=3000),输出a/b的循环小数表示以及循环节长度. 例如,a=5,b=43,小数表示为0.(1162790697674418 ...

  3. July 算法习题 - 字符串4(全排列和全组合)

    https://segmentfault.com/a/1190000002710424 思想:当前层各节点首元素不同,则各节点的剩余元素也不同:下一层节点交换范围为首元素以外的元素 全排列算法: vo ...

  4. 算法习题---4-9数据挖掘(Uva1591)

    一:题目 这是最懵逼的一道题,什么鬼......... [刷题]算法竞赛入门经典(第2版) 4-9/UVa1591 - Data Mining(详细题目看这个吧,不想多说) 二:代码实现 #defin ...

  5. tarjan算法 习题

    dfs树与tarjan算法 标签(空格分隔): 517coding problem solution dfs树 tarjan Task 1 给出一幅无向图\(G\),在其中给出一个dfs树\(T\), ...

  6. 【算法习题】正整数数组中和为sum的任意个数的组合数

    1.递归实现(参考:https://blog.csdn.net/hit_lk/article/details/53967627) public class Test { @org.junit.Test ...

  7. 算法习题-FFT

    Q1(hdu1402): 给出两个很大的数字A,B,计算二者乘积. 分析:这个题目java应该能过,用FFT做能够加速计算.这里将字符串A按权(10进制)展开,前面的系数就是多项式的系数,这样就构造出 ...

  8. 笔试算法题(08):输出倒数第K个节点

    出题:输入一个单向链表,要求输出链表中倒数第K个节点 分析:利用等差指针,指针A先行K步,然后指针B从链表头与A同步前进,当A到达链表尾时B指向的节点就是倒数第K个节点: 解题: struct Nod ...

  9. 算法习题---5-8图书管理系统*****<双向迭代器>(UVa230)

    一:题目 就是输入一系列书本名和作者名,然后输入命令模拟借书和还书,再输出归还的书的摆放位置.要求有两点: 需要对归还的书做特殊排序处理:作者名相同,则书本按书名从小到大排序:否则书本按作者名大小排序 ...

随机推荐

  1. springboot Properties加载顺序源码分析

    关于properties: 在spring框架中properties为Environment对象重要组成部分, springboot有如下几种种方式注入(优先级从高到低): 1.命令行 java -j ...

  2. Java stackoverflowerror异常与outofmemoryerror异常区别

    1.stackoverflow: 每当java程序启动一个新的线程时,java虚拟机会为他分配一个栈,java栈以帧为单位保持线程运行状态:当线程调用一个方法是,jvm压入一个新的栈帧到这个线程的栈中 ...

  3. EntityFramework 事物引发的问题

    前记 还是最近做的日志模块,今天做最后的入库工作.在测试入库日志记录时,总是出现怪异的问题. 开启服务开始接收 Kafka 的消息,第一条数据没有问题,后面的都如不了库.很是懵~~~ 调试了很久定位在 ...

  4. Springboot与ActiveMQ、Solr、Redis中分布式事物的初步探索

    Springboot与ActiveMQ.Solr.Redis中分布式事物的初步探索 解决的场景:事物中的异步问题,当要求数据库与solr服务器的最终一致时. 程序条件: 利用消息队列,当数据库添加成功 ...

  5. java UDP 通信:服务端与客服端

    import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import j ...

  6. ***PHP preg_match正则表达式的使用 转载:https://www.cnblogs.com/kenshinobiy/p/4443600.html

    第一,让我们看看两个特别的字符:‘^’和‘$’他们是分别用来匹配字符串的开始和结束,以下分别举例说明 : "^The": 匹配以 "The"开头的字符串; &q ...

  7. tomcat实现文件上传下载

    实现下载 修改server.xml修改web.xml   实现上传 实现客户端的上传post请求代码实现 实现服务端的处理   小结         实现下载 实现下载需要  - 修改Tomcat中的 ...

  8. stm32 HardFault_Handler调试及问题查找方法——飞思卡尔

    看到有朋友遇到Hard Fault 异常错误,特地找到一篇飞思卡尔工程师写的一片经验帖,定位Hard Fault 异常. Kinetis MCU 采用 Cortex-M4 的内核,该内核的 Fault ...

  9. myeclipse关掉references

    去掉下面两个勾选:

  10. java获取远程服务器应用程序服务状态

    package lct.conference.test; import java.io.BufferedReader; import java.io.IOException; import java. ...