问题描述

  我们知道,整数做除法时,有时得到有限小数,有时得到无限循环小数。
  如果我们把有限小数的末尾加上无限多个0,它们就有了统一的形式。

  本题的任务是:在上面的约定下,求整数除法小数点后的第n位开始的3位数。

输入格式
  一行三个整数:a b n,用空格分开。a是被除数,b是除数,n是所求的小数后位置(0<a,b,n<1000000000)
输出格式
  一行3位数字,表示:a除以b,小数后第n位开始的3位数字。
样例输入
1 8 1
样例输出
125
样例输入
1 8 3
样例输出
500
样例输入
282866 999000 6
样例输出
914
思路:我们以3/7举例,下面是手写的常规除法的计算过程。

比如n=4时,我们计算的是小数第四位,那么很明显就是40除于7的值,所以我们只需要知道第四位小数对应的哪个被除数是谁就行,用变量sa表示被除数,则第一位小数就是sa/7,余数就是下一个小数对应的被除数,那么用余数更新sa,一次类推可以计算出所有的小数,注意上图第一个被除数30如果在下面再次出现则容易知道接下来会重复计算,意味着产生循环节,所以我们可以通过循环节长度更新n,降低时间复杂度。

代码
  1. #include<bits/stdc++.h>
  2.  
  3. using namespace std;
  4.  
  5. int main()
  6. {
  7. int a,b,n;
  8. int sa;
  9. cin >> a >> b >> n;
  10. sa=a%b;//初始化sa,sa是求每次相除的余数
  11. for(int i=;i<=n;i++){
  12. sa=sa%b*;//在本轮循环相除后余数发生改变
  13. //cout << sa <<" "<<sa%b <<" "<<a%b << endl;
  14. if(sa%b==a%b){//如果下一次循环(注意sa%b是下一次循环的余数)的余数 等于初始的余数,说明接下来的循环或重复之前的计算
  15. n%=i;//n缩小(这是降低时间复杂度的关键) ,
  16. i=;//重新开始遍历
  17. }
  18. }
  19. for(int i=;i<=;i++){
  20. cout << sa/b;//输出该位置计算结果 ,注意如果是有限小数切sa=0时,接下来都是输出0
  21. sa=sa%b*;//下一次计算的余数
  22. }
  23. return ;
  24. }

但是仔细一想上个代码其实是不完全正确的,或不完美的,虽然可以通过测试系统,因为上个代码默认循环节的第一个数字就是小数点后的第一个数字,但是很许多循环小数并非如此

这是第三个测试用例相除的结果,发现循环节是149,从第四个数字开始,如果我们要查询结果数亿之后的某个数的后三位,上个代码明显超时,所以需考虑循环节不在第一位的情况,

在上个代码上修改如下

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. int t=;
  4. int array[];
  5. int compare(int m)//得到循环节开始的下标
  6. {
  7. for(int i=;i<t;i++){
  8. if(array[i]==m) return i;//此时第二个循环节的第一个数字遇到第一个循环节的第一个数字,返回第一个循环节开始的下标
  9.  
  10. }
  11. return ;
  12. }
  13. int main()
  14. {
  15. int a,b,n;
  16. int sa;
  17. cin >> a >> b >> n;
  18. int m=;//表示还没遇到循环节
  19. int num=;
  20.  
  21. memset(array,,sizeof(array));
  22. sa=a%b;//初始化sa,sa是求每次相除的余数
  23. for(int i=;i<=n;i++){
  24. if(m== && i!=) array[t++]=sa%b;
  25. if(m== && i==) array[t++]=sa;
  26. sa=sa%b*;//在本轮循环相除后余数发生改变
  27. if(m==)
  28. {
  29. int aa=sa%b;
  30. num=compare(aa);
  31. // cout << num << endl;
  32. }
  33. if(num!=&&m!=){
  34. n%=(i-num+);
  35. n+=(num-);
  36. i=;
  37. m=;
  38. }
  39. //if(nu)
  40. }
  41. for(int i=;i<=;i++){
  42. cout << sa/b;//输出该位置计算结果 ,注意如果是有限小数切sa=0时,接下来都是输出0
  43. sa=sa%b*;//下一次计算的余数
  44. }
  45. return ;
  46. }

下面的小demo是计算循环节的,根据上个代码衍生出来的

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. int t=;
  4. int array[];
  5. int compare(int m)//得到循环节开始的下标
  6. {
  7. for(int i=;i<t;i++){
  8. if(array[i]==m) return i;//此时第二个循环节的第一个数字遇到第一个循环节的第一个数字,返回第一个循环节开始的下标
  9.  
  10. }
  11. return ;
  12. }
  13. int main()
  14. {
  15. //freopen("D:/Data.txt","r",stdin);
  16. int a,b;
  17. int sa;
  18. cin >> a >> b;
  19. int num=;
  20. memset(array,,sizeof(array));
  21. sa=a%b;
  22. for(int i=;i<;i++){
  23. if(sa%b==) {t=; break;}
  24. if(i!=) array[t++]=sa%b;
  25. if(i==) array[t++]=sa;
  26. sa=sa%b*;
  27. int aa=sa%b;
  28. num=compare(aa);
  29. if(num!=) break;
  30.  
  31. }
  32. if(t==) cout << "不存在循环节" << endl;
  33. else{
  34. sa=a%b;
  35. for(int i=;i<=t;i++){
  36. if(i>num) cout << sa/b;//输出该位置计算结果 ,注意如果是有限小数切sa=0时,接下来都是输出0
  37. sa=sa%b*;//下一次计算的余数
  38. }
  39. }
  40. return ;
  41. }

历届试题 小数第n位的更多相关文章

  1. Java实现 蓝桥杯 历届试题 小数第n位

    历届试题 小数第n位 时间限制:1.0s 内存限制:256.0MB 问题描述 我们知道,整数做除法时,有时得到有限小数,有时得到无限循环小数. 如果我们把有限小数的末尾加上无限多个0,它们就有了统一的 ...

  2. 历届试题 小数第n位-(同余公式+快速幂)

    问题描述 我们知道,整数做除法时,有时得到有限小数,有时得到无限循环小数. 如果我们把有限小数的末尾加上无限多个0,它们就有了统一的形式. 本题的任务是:在上面的约定下,求整数除法小数点后的第n位开始 ...

  3. 历届试题 小数第n位(小技巧)

    问题描述 我们知道,整数做除法时,有时得到有限小数,有时得到无限循环小数. 如果我们把有限小数的末尾加上无限多个0,它们就有了统一的形式. 本题的任务是:在上面的约定下,求整数除法小数点后的第n位开始 ...

  4. 历届试题 小数第n位 (求循环节)

    只要被除数出现重复,就表明循环节出现了.即使商不是循环小数,也可以补0作为循环节,这样就可以统一处理了. AC代码 #include <stdio.h> #include <vect ...

  5. 算法笔记_186:历届试题 高僧斗法(Java)

    目录 1 问题描述 2 解决方案   1 问题描述 问题描述 古时丧葬活动中经常请高僧做法事.仪式结束后,有时会有“高僧斗法”的趣味节目,以舒缓压抑的气氛. 节目大略步骤为:先用粮食(一般是稻米)在地 ...

  6. 蓝桥杯 历届试题 剪格子(dfs搜索)

    历届试题 剪格子 时间限制:1.0s   内存限制:256.0MB 问题描述 如下图所示,3 x 3 的格子中填写了一些整数. +--*--+--+ |* || +--****--+ ||* | ** ...

  7. 蓝桥杯 历届试题 PREV-34 矩阵翻硬币

    历届试题 矩阵翻硬币   时间限制:1.0s   内存限制:256.0MB 问题描述 小明先把硬币摆成了一个 n 行 m 列的矩阵. 随后,小明对每一个硬币分别进行一次 Q 操作. 对第x行第y列的硬 ...

  8. Java实现蓝桥杯历届试题回文数字

    历届试题 回文数字 时间限制:1.0s 内存限制:256.0MB 提交此题 问题描述 观察数字:12321,123321 都有一个共同的特征,无论从左到右读还是从右向左读,都是相同的.这样的数字叫做: ...

  9. Java实现蓝桥杯历届试题高僧斗法

    历届试题 高僧斗法 时间限制:1.0s 内存限制:256.0MB 提交此题 锦囊1 锦囊2 问题描述 古时丧葬活动中经常请高僧做法事.仪式结束后,有时会有"高僧斗法"的趣味节目,以 ...

随机推荐

  1. 关于Oracle to_char()函数中的IW,WW 周别显示

    1)ww的算法为每年1月1日为第一周开始,date+6为每一周结尾 例如20050101为第一周的第一天,而第一周的最后一天为20050101+6=20050107 公式 每周第一天 :date + ...

  2. 二进制(signed or unsigned)补码

    在计算机系统中,数值一律用补码来表示(存储). 主要原因:使用补码,可以将符号位和其它位统一处理:同时,减法也可按加法来处理.另外,两个用补 码表示的数相加时,如果最高位(符号位)有进位,则进位被舍弃 ...

  3. Linux系统SCSI磁盘扫描机制解析及命令实例(转)

    转载请在文首保留原文出处:EMC中文支持论坛 介绍 Linux系统扫描SCSI磁盘有几种方式?Linux新增LUN之后,能否不重启主机就认出设备?如果安装了PowerPath,动态添加/删除LUN的命 ...

  4. RabbitMQ操作方法

    /// <summary> /// 消费者(消息) /// </summary> public class CustmerMq { /// <summary> // ...

  5. leetcode582

    public class Solution { public IList<int> KillProcess(IList<int> pid, IList<int> p ...

  6. Mycat之日志分析 select * from travelrecord order by id limit 100000,100 的执行过程

    解释:mycat在执行分页排序的时候,分成2步走.如果M很大,会改写成 limit 0,m+n, 然后在每个MYSQL分片上排序后还需要在mycat汇总输出,所以会很慢.下面是详细执行计划以及日志输出 ...

  7. UIAtlas

    [UIAtlas] UIAtlas is a container that has coordinate information for a bunch of sprites. AtlasType有2 ...

  8. js确定来源页然后跳转

    <script type="text/javascript"> function Navigate() { if(document.referrer == 'http: ...

  9. 浏览器get请求到java后台的值是乱码

     get方式提交的参数编码,只支持iso8859-1编码. 因此,如果里面有中文,在后台就需要转换编码,如下 String zhongwen = request.getParameter(" ...

  10. OS线程模型

    线程模型 N对1 内核线程 映射 用户进程, 用户进程里可以启多个线程 1对1 内核线程和用户线程 1对1 Linux采用这种方式 N对M 用户线程被抽象为更轻量的线程, 内核线程和轻量的线程对应 进 ...