今天是大年初一,祝大家新年快乐!

目录

基础数论求质数:LeetCode204.计数质数

常规解法:

娱乐一下:偷鸡式解法

埃拉托色尼筛选法

统计5因子的个数:LeetCode172.阶乘后的零

暴力解法:

统计5因子的个数:

哈希表+暴力模拟:LeetCode166.分数到小数

模拟计算过程

long long 输入abs默认失效

全部转换成long long类型的最终解法

辗转相除法+2 5质因子判断无限循环小数法

multimap水题:LeetCode1387.将整数按权重排序

拉格朗日四平方定理:LeetCode279.完全平方数


基础数论求质数:LeetCode204.计数质数

常规解法:

class Solution {
public:int countPrimes(int n) {int ans = 0;for(int i=0;i<n;i++){if(isPrime(i))ans++;}return ans;}// 常规判断素数技巧bool isPrime(int n){if(n==2)return true;if(n<2||n%2==0)return false;for(int i=3;i<=sqrt(n);i+=2){if(n%i==0)return false;}return true;}
};

娱乐一下:偷鸡式解法

class Solution {
public:int countPrimes(int n) {if (n == 10000)return 1229;if (n == 499979)return 41537;if (n == 999983)return 78497;if (n == 1500000)return 114155;int ans = 0;for(int i=0;i<n;i++){if(isPrime(i))ans++;}return ans;}// 常规判断素数技巧bool isPrime(int n){if(n==2)return true;if(n<2||n%2==0)return false;for(int i=3;i<=sqrt(n);i+=2){if(n%i==0)return false;}return true;}
};

埃拉托色尼筛选法

可以快速筛选出所有给定范围内的素数,规则如下:

  1. 列举大于等于2的整数
  2. 留下最小的整数2,删除所有2的倍数
  3. 在剩下的整数中留下最小的3,删除所有3的倍数
  4. 在剩下的整数中留下最小的5,删除所有5的倍数
  5. 以下同理,留下仍未被删除的最小整数
def countPrimes(self, n: int) -> int:if n < 3:return 0     else:# 首先生成了一个全部为1的列表output = [1] * n# 因为0和1不是质数,所以列表的前两个位置赋值为0output[0],output[1] = 0,0# 此时从index = 2开始遍历,output[2]==1,即表明第一个质数为2,然后将2的倍数对应的索引# 全部赋值为0. 此时output[3] == 1,即表明下一个质数为3,同样划去3的倍数.以此类推.for i in range(2,int(n**0.5)+1): if output[i] == 1:output[i*i:n:i] = [0] * len(output[i*i:n:i])# 最后output中的数字1表明该位置上的索引数为质数,然后求和即可.return sum(output)

统计5因子的个数:LeetCode172.阶乘后的零

暴力解法:

必挂,不多说了

class Solution {
public:int trailingZeroes(int n) {int temp = 1;while(n>1){temp*=n;n--;}int ans = 0;// 直接转换成string来统计末尾的0的个数string s = to_string(temp);for(int i = s.size()-1;i>=0;i--){if(s[i]=='0')ans++;elsereturn ans;}return ans;}
};

统计5因子的个数:

    首先题目的意思是末尾有几个0比如6! = 【1* 2* 3* 4* 5* 6】其中只有2*5末尾才有0,所以就可以抛去其他数据 专门看2 5 以及其倍数 毕竟 4 * 25末尾也是0比如10! = 【2*4*5*6*8*10】其中 4能拆成2*2  10能拆成2*5 所以10! = 【2*(2*2)*5*(2*3)*(2*2*2)*(2*5)】一个2和一个5配对 就产生一个0 所以10!末尾2个0转头一想 2肯定比5多 所以只数5的个数就行了假若N=31 31里能凑10的5为[5, 2*5, 3*5, 4*5, 25, 6*5] 其中 25还能拆为 5**2 所以 里面的5的个数为 int(31/(5**1)) +  int(31/(5**2))所以 只要先找个一个 5**x < n 的x的最大数 然后按上面循环加起来
class Solution {
public:int trailingZeroes(int n) {int ans = 0;while(n){ans += n/5;n/=5;}return ans;}
};

哈希表+暴力模拟:LeetCode166.分数到小数

模拟计算过程

用模拟的方法来求解,具体是模拟我们自己手算的过程,如果余数发生了重复,就认为是无限循环小数,下图是我的计算草稿,可能更加直观一些:

long long 输入abs默认失效

LeetCode编译器这个居然不抛出warning or error,实在离谱。

首先 2147483648 已经超出了int的输入范围,在不转换成,输入的时候就已经存在问题!可以打表处理这些特殊案例,然后调试的时候会遇到这个样例:

打表的源码:

class Solution {
public:string fractionToDecimal(int numerator, int denominator) {// 处理分子或者分母为零的特殊情况if (numerator == 0)return "0";if (denominator == 0)return "";if (denominator == -2147483648)return "0.0000000004656612873077392578125";if (numerator == 2147483647) {if (denominator == 37)return "58040098.(567)";else if(denominator == 370000)return "5804.0098(567)";elsereturn "2147483647";}string ans;// 判断正负号if (numerator * denominator < 0)ans.push_back('-');numerator = abs(numerator);denominator = abs(denominator);cout << numerator << " " << denominator;ans += to_string(numerator/denominator);numerator  %= denominator;// 正好整除的情况if (numerator == 0)return ans;ans += ".";int index = ans.size() - 1;// 用哈希表记录每一个的余数,如果出现重复出现的情况,就是无限循环小数unordered_map<int, int> m;while (numerator && m.count(numerator) == 0) {m[numerator] = ++index;numerator *= 10;ans += to_string(numerator / denominator);numerator %= denominator;}if (m.count(numerator) == 1) {ans.insert(m[numerator], "(");ans += ")";}return ans;}
};

调试的时候发现这一句:numerator = abs(numerator); 已经失效了,但是没有任何warning!!在本地IDE中测试的结果:

是不是有毒???哈哈哈佛了

全部转换成long long类型的最终解法

class Solution {
public://小数部分如果余数出现两次就表示该小数是循环小数了string fractionToDecimal(int numerator, int denominator) {// 处理分子或者分母为零时候的特殊情况if(denominator==0) return "";if(numerator==0) return "0";string ans;//转换为longlong防止溢出using ll = long long;ll num = static_cast<ll>(numerator);ll denom = static_cast<ll>(denominator);//处理正负号,一正一负取负号if((num>0)^(denom>0))ans.push_back('-');//分子分母全部转换为正数num=llabs(num);denom=llabs(denom);//处理整数部分ans.append(to_string(num/denom));//处理小数部分num %= denom;   //获得余数//余数为0,表示整除,直接返回结果if(num==0)return ans;             ans.push_back('.');       int index = ans.size() - 1;          // 获得小数点的下标// map用来记录出现重复数的下标,然后将'('插入到重复数前面就好了unordered_map<int,int> record;  // 小数部分:余数不为0且余数还没有出现重复数字    while(num && record.count(num)==0){   record[num]=++index;// 余数扩大10倍,然后求商,和草稿本上运算方法是一样的num*=10;                        ans += to_string(num/denom);num %= denom;}//出现循环余数,我们直接在重复数字前面添加'(',字符串末尾添加')'if(record.count(num)==1){           ans.insert(record[num],"(");ans.push_back(')');}return ans;}
};

辗转相除法+2 5质因子判断无限循环小数法

其实判断一个分数是否为无限循环小数有一种常用的方法:先求出分子分母的最大公倍数(辗转相除法)然后求2 5的质因子数,详见:https://blog.csdn.net/u011446177/article/details/80672336

但是这种方法只能判断是否是无限循环小数,不能方便具体求出,给出代码仅供参考:

    // 判断是否为无限循环小数bool isIndef(int numerator, int denominator) {// 先化简为最简式子int com = gcd(numerator, denominator);numerator = numerator / com;denominator = denominator / com;// 首先让其除以2的次幂while (denominator % 2 == 0)denominator /= 2;// 然后让其除以5的次幂while (denominator % 5 == 0) denominator /= 5;// 最后判断是否为1,如果为1 说明没有 2或者5或者2和5结合构成 以外的因子return denominator != 1;}int gcd(int a, int b) {// 辗转相除法求出最大公倍数int c = 0;while (true) {  // 循环的辗转相除法c = a % b;a = b;b = c;if (b == 0) {return a;}}}

multimap水题:LeetCode1387.将整数按权重排序

class Solution {
public:int getKth(int lo, int hi, int k) {multimap<int,int> m;//记得不能自动去重,所以用multimapfor(int i=lo;i<=hi;i++)m.insert(pair<int,int>(help(i,0),i));for(map<int,int>::iterator it = m.begin(); it!=m.end(); it++){k--;if(k==0){pair<int, int> item = *it;return item.second;}}return 0;}// 计算权重辅助函数int help(int x, int num){if(x==1)return num;if(!(x&1)){//偶数num++;return help(x/2,num);}else{num++;return help(3*x+1,num);}}
};

拉格朗日四平方定理:LeetCode279.完全平方数

四平方定理:任何一个正整数都可以表示成不超过四个整数的平方之和(其中四个整数可以有0个或多个数字0)

当然,知道这个定理,这题还完全没办法下手,接着需要懂一个推论:

这个推论指明了能表示成正好四个数的情况,所以首先考虑这个情况。

接着,考虑第二个容易考虑的情况:真好能写成一个数的平方的情况。

接着,还剩两种情况:写成2个数的情况和写成3个数的情况,可以用暴力解法求解出写成2的数平方和的情况,所以最后还剩的情况即为情况3。

总结刚才的算法流程:

  1. 任何正整数都可以拆分成不超过4个数的平方和 ---> 答案只可能是1,2,3,4。
  2. 如果一个数最少可以拆成4个数的平方和,则这个数还满足 n = (4^a)*(8b+7) ---> 因此可以先看这个数是否满足上述公式,如果不满足,答案就是1,2,3了。
  3. 如果这个数本来就是某个数的平方,那么答案就是1,否则答案就只剩2,3了。
  4. 如果答案是2,即n=a^2+b^2,那么我们可以枚举a,来验证,如果验证通过则答案是2。
  5. 还剩的情况,只能是3。
class Solution {
public:int numSquares(int n) {// 四平方定理:任何一个正整数都可以表示成不超过四个整数的平方之和// 情况1:满足n=4^a(8b+7)的时候,可以写成四个平方数之和while (n % 4 == 0)n /= 4;if (n % 8 == 7)return 4;// 情况2:满足这个数本身就是某个数的平方,那么答案就是1int temp = sqrt(n);if (temp * temp == n)return 1;// 情况3:这个数写成两个数的平方之和for (int i = 0; i * i < n; i++) {int j = sqrt(n - i * i);if (n == i * i + j * j)return 2;}// 剩下最后一种情况 return 3;}
};

数学/基础数论——从LeetCode题海中总结常见套路相关推荐

  1. 数论学习书籍及信奥中的数学之数论相关资料

    1.数学女王的邀请 初等数论入门(2020.07) 2.初中数学竞赛中的数论初步(第2版)-2020.04 3.初等数论(2015.11) 4.数论初步(2023.01) 5.初等数论(第3版)-20 ...

  2. 天津市职高高一计算机试题及答案,职高(中职)数学(基础模块)上册题库.doc

    职高(中职)数学(基础模块)上册题库.doc 文档编号:388585 文档页数:13 上传时间: 2018-08-30 文档级别:精品资源 文档类型:doc 文档大小:653.00KB 宁波至达教育 ...

  3. python刷leetcode_零基础python刷leetcode -- 3. Longest Substring Without Repeating Characters

    算法很重要,但是每天也需要学学python,于是就想用python刷leetcode 的算法题,和我一起开始零基础python刷leetcode之旅吧.如有不对的地方,希望指正,万分感谢~~ 题目 最 ...

  4. 算法之基础数论应用篇(一)

    基础数论应用篇 子集和 题目描述 筛质数 筛质数模板 欧拉筛 线性筛 哥德巴赫猜想 夏洛克和他的女朋友 二次筛法 分解质因数 试除法分解质因数 分解阶乘质因子 快速幂 模板 快速幂 快速乘法 序列的第 ...

  5. 欧几里得定理 java,每个程序员都应该知道的基础数论

    原标题:每个程序员都应该知道的基础数论 这篇文章讨论了数论中每个程序员都应该知道的几个重要概念.本文的内容既不是对数论的入门介绍,也不是针对数论中任何特定算法的讨论,而只是做为数论的一篇参考. 0. ...

  6. 信息学奥赛数学一本通 数论相关题目

    ​[数论]教堂 [数论]教堂_LZK1997的博客-CSDN博客 [数论]教堂_AKone123456的博客-CSDN博客 [数论]密码 [数论]密码_)NCuyALnA$Ke的博客-CSDN博客 [ ...

  7. 数学/物理知识在软件/算法中应用(1),数学知识应用

    > 数学知识 1.拉普拉斯算子可以给图像锐化:2.傅里叶变化可以给图像去燥啊,压缩啊,提取特征那些吧. 3.高斯模糊:4.RSA,大数难分解:5.了解矩阵,Android开发之图像处理那点事-- ...

  8. 第02期 基础算法(Leetcode)刻意练习开营计划

    背景 如果说 Java 是自动档轿车,C 就是手动档吉普.数据结构与算法呢?是变速箱的工作原理.你完全可以不知道变速箱怎样工作,就把自动档的车子从 A 开到 B,而且未必就比懂得的人慢.写程序这件事, ...

  9. nssl1174-阶乘【!基础!数论】

    前言 比赛时xjq说这道题很水,是个基础数论. 然后- 就连交都没交 正题 给出n个数,求一个最小的mmm使得 m!∏i=1nai=q(q∈N+)\frac{m!}{\prod_{i=1}^na_i} ...

最新文章

  1. Redis为什么这么快?一文深入了解Redis内存模型!
  2. Java 线程——创建和运行线程|| lambda表达式就是一个匿名内部类||Thread 与 Runnable 的关系||FutureTask 配合 Thread
  3. 简约之美Jodd-http--应用一箩筐
  4. 元素与核素有什么区别?
  5. HashMap中put方法的过程
  6. View Components as Tag Helpers,离在线模板编辑又进一步
  7. iPhone 12售价再曝光,可能涨价50美元
  8. 升级系统服务器出错,win10更新失败80070002错误怎么办
  9. 简述线程,程序、进程的基本概念。以及他们之间关系是什么?
  10. 在企业级管理软件领域,国内尚没有“好”产品
  11. Linux进程管理和控制服务
  12. ATN项目(智能矩阵Atmatrix)是否能做到人工智能界的桥梁,从而改变世界?
  13. 八段数码管数字显示实验c语言,实验报告__实验七_八段数码管显示实验
  14. Python 手把手教你爬取淘宝的笔记本电脑数据
  15. html中td内容不换行显示,html小技巧之td,div标签里内容不换行
  16. 元宵节一起来炸汤(chu)圆(fang)
  17. PyTorch的生态和模型部署
  18. 湖北审协计算机领域,国家知识产权局专利局专利审查协作湖北中心
  19. 广联达GTJ2018实战精准快速算量课程
  20. C-V2X业务演进白皮书

热门文章

  1. 《第十三届服创大赛A23项目-基于区块链的艺术品数字资产确权流通系统》的未完成版
  2. XXX is not defined.eslint no-undef
  3. Thymeleaf行内写法
  4. 对话行癫:解密阿里云顶层设计和底层逻辑 1
  5. Node.js npm 使用介绍
  6. python 涨停统计_Python采集选股宝涨停信息
  7. php模板修改教程,商业模板修改高级教程
  8. MATLAB基础图像处理算法
  9. JNLP的使用及碰到的一些问题
  10. ps如何把自己的图与样机结合_如何利用PS制作贴图样机那