文章目录

  • 1.引言
  • 2.最大公约数与最小公倍数
    • 2.1最大公约数
    • 2.2最小公倍数
  • 3.筛法和打表
  • 4.进制转换
  • 5.角度问题(1rad=180°/π)
  • 6.同余定理
  • 7.容斥原理
  • 8.距离度量公式
  • 9.中位数定理
  • 每日古诗一首

1.引言

  在Leetcode上刷题时,会遇到一些用数据结构和常用算法无法解决的数学问题,巧妙地运用一些数学知识可以很快地解决这些问题。下面我们将介绍一些常用的解决数学问题的技巧,包括但不限于:最大公约数与最小公倍数、筛法和打表、同余定理、容斥原理、中位数定理等。

2.最大公约数与最小公倍数

  对于两个正整数a和b,其最最大公约数与最小公倍数的乘积等于两数之积:

最大公约数 × 最小公倍数 = a × b

2.1最大公约数

  辗转相除法,又名欧几里得算法,是求两个数的最大公约数(the Great Common Divisor,GCD)的一种方法,具体做法是:用较大数除以较小数,再用出现的余数(第一余数)去除除数,再用出现的余数(第二余数)去除第一余数,如此反复,直到最后余数是0为止,那么最后的除数就是这两个数的最大公约数。(第k余数即第k次计算出现的余数)

int GCD(int a,int b){//辗转相除法   被除数/除数=商if(a%b==0) return b;//这里的a b大小不重要,因为即使a<b,到了下面又会换回来else return GCD(b,a%b);
}

若要求n个数的最大公约数,可以先求2个数的最大公约数,然后用这两个数的最大公约数和第三个数求最大公约数,然后再用前三个的最大公约数和第四个求最大公约数,以此类推。

2.2最小公倍数

  可以用两个数相乘再除以最大公约数来求得这两个数的最小公倍数(the Least Common Multiple,LCM):

int LCM(int a,int b){//辗转相除法   被除数/除数=商return (a*b)/GCD(a,b);
}

求n个数的最小公倍数同上面求n个数的最大公约数。

例题:1979.找出数组的最大公约数(简单)

题目描述:
  给你一个整数数组 nums ,返回数组中最大数和最小数的最大公约数两个数的最大公约数是能够被两个数整除的最大正整数。

输入输出样例:

输入 :nums = [2,5,6,9,10]
输出: 2
解释:
nums 中最小的数是 2
nums 中最大的数是 10
2 和 10 的最大公约数是 2
提示:

  • 2 <= nums.length <= 1000
  • 1 <= nums[i] <= 1000

题解:
  只需要模拟题意,找出来数组中的最大值和最小值(可以用C++内置函数,也可以自己写for循环),然后利用上面的GCD函数即可求出。

int GCD(int a,int b){if(a%b==0)return b;else return GCD(b,a%b);
}
int findGCD(vector<int>& nums) {int n=nums.size();int max = *max_element(nums.begin(),nums.end());int min = *min_element(nums.begin(),nums.end());return GCD(min,max);
}

PIPIOJ例题:1352.多个数的最小公倍数(简单)
  解答见:巧解数学问题——练习题链接及解答

3.筛法和打表

  埃氏筛法是非常常用的判断一个整数是否是质数的方法。用埃氏筛法筛选出n以内的质数:从1到n遍历,假设当前遍历到i,则把所有小于n的且是i的倍数的整数标记为合数;遍历完成后,没有被标记为合数的数字即为质数。时间复杂度为:O(nloglogn)。

q[1]=1;//1为合数
for(int i=2;i<n;i++){if(q[i]==0){//q[i]=0表示i为质数for(int j=2*i;j<n;j+=i)q[j]=1;}
}

例题:204计数质数(中等)

题目描述:
  给定整数n,返回 所有小于非负整数n的质数的数量 。

输入输出样例:

输入 :n = 10
输出: 4
解释:小于 10 的质数一共有 4 个, 它们是 2, 3, 5, 7 。
提示: 0 <= n <= 5*106

题解:
  根据埃氏筛法标记处1~n以内的合数,每标记一次,质数数量减一。

 int countPrimes(int n) {if(n<=2)return 0;int num=n-2;//去除1和n本身vector<int> q(n,0);q[1]=1;for(int i=2;i<n;i++){if(q[i]==0){//q[i]=0表示i为质数for(int j=2*i;j<n;j+=i){if(q[j]==0){//避免重复q[j]=1;num--;}}}}return num;}

PIPIOJ例题:1044.七夕节(简单)
  解答见:巧解数学问题——练习题链接及解答

4.进制转换

  任何类型的进制转换都可以参照十进制转二进制的形式,使用短除法进行转换。以下面13和10为例,展示具体转换过程。

13转为二进制 10转为二进制
13/2=6…1 10/2=5…0
6/2=3…0 5/2=2…1
3/2=1…1 2/2=1…0
1/2=0…1 1/2=0…1
1101 1010

等到商为0的时候结束运算,从下往上把余数连接起来,就得到了最终转换的二进制的值。
例题:504.七进制数(简单)

题目描述:
  给定一个整数 num,将其转化为7进制数,并以字符串的形式输出。

输入输出样例:

输入 :num = 100
输出: “202”
解释:100的七进制表示为:100=2 * 72+0 * 71+2 * 70
提示:

  • -107 <= num <= 107

题解:
  根据短除法,每次记录余数,最后反转字符串即可得到答案。

string convertToBase7(int num) {string ans;int tmp = abs(num);if(num==0)return "0";while(tmp){int remainder=tmp%7;//记录余数ans+='0'+remainder;//将整数转换为字符类型tmp/=7;}reverse(ans.begin(),ans.end());return num<0 ? "-"+ans : ans;
}

例题:1017. 负二进制转换(中等)
  解答见:巧解数学问题——练习题链接及解答

5.角度问题(1rad=180°/π)

  关于角度问题,总结以下注意事项:
(1)sin,cos,tan这三个函数使用时都只能用弧度,不能够用角度。
(2)asin,acos,atan这三个函数返回值都为弧度。
(3)PI = acos(-1) , 若OJ题中有用到,请用该公式求π。
例题:PIPIOJ1154.球的半径和体积(简单)

题目描述:
  输入球的中心点和球上某一点的坐标,计算球的半径和体积。

输入输出样例:

输入 :输入包含多组测试用例。对于每一组测试用例,输入球的中心点和球上某一点的坐标,以如下形式输入:x0 y0 z0 x1 y1 z1
输出: 对于每组输入,输出球的半径和体积,结果保留三位小数.
解释:输入:0 0 0 1 1 1 输出:1.732 21.766

题解:
  注意用到π的表达,以及精度问题。球的半径:三维欧几里得距离。球的体积:V=4/3πR3,球的表面积:S=4πR2

#include<bits/stdc++.h>
using namespace std;
const double PI = acos(-1);
int main(){double x0,y0,z0,x1,y1,z1;while(scanf("%lf%lf%lf%lf%lf%lf",&x0,&y0,&z0,&x1,&y1,&z1)!=EOF){double r,v; r = sqrt((x0-x1)*(x0-x1)+(y0-y1)*(y0-y1)+(z0-z1)*(z0-z1));v = 4.0/3 * PI * pow(r,3);printf("%.3f %.3f\n",r,v); }return 0;
}

6.同余定理

  (1)(a±b)%mod = (a%mod±b%mod)%mod。注意:如果为减法的话a%mod-b%mod可能为负数,所以后面+个mod:(a%mod-b%mod+mod)%mod
  (2)(ab)%mod = (a%modb%mod)%mod。
例题:PIPIOJ1103.PIPI的数学题1(简单)

题目描述:
  PIPI现在有一个很大的数字N,他想知道这个数对p取模的结果。

输入输出样例:

输入 :输入包含多组测试用例。对于每一组测试用例,包含一个正整数N(N<1010000)和一个模数p(0<p<232)
输出: 对于每一组测试用例,输出 N%p
解释:
样例输入:
10 30
30 10
100 33
样例输出:
10
0
1

题解:
  注意输入是一个很大的数,要用字符串读入,利用同余定理即可轻松解决。

#include<bits/stdc++.h>
using namespace std;
const int N=1e4+5;
char s[N];
int main()
{long long p;while(scanf("%s%lld",s,&p)!=EOF){int n=strlen(s);long long tmp=0;for(int i=0;i<n;i++){tmp = (tmp*10+s[i]-'0')%p;}printf("%lld\n",tmp);}return 0;
}

7.容斥原理

  (1)两个集合的容斥关系公式:

|A∪B| = |A|+|B| - |A∩B |(∩:重合的部分)

  (2)三个集合的容斥关系公式:

|A∪B∪C| = |A|+|B|+|C| - |A∩B| - |B∩C| - |C∩A| + |A∩B∩C|

例题:PIPIOJ1341.PIPI学容斥(中等)

题目描述:
  给定正整数 n , a, b, c 。让你求出1~n中能够被 a或 b或 c整除的数的个数。

输入输出样例:

输入 :输入包含多组数据。每一组数据包含三个数字 n , a , b , c 。(1<=a, b, c, n <=1e9)。
输出: 对于每一组测试用例,输出1~n中能够被a 或者 b 或者 c整除的数的个数。
解释:
样例输入:
1000 2 3 5
100 2 3 5
样例输出:
734
74

  1~n中能够被a整除的数的个数就是:n/a,能同时被a或者b整除的数的个数就是:n/(a和b的最小公倍数)。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll gcd(ll a, ll b){if(a%b==0)return b;else return gcd(b,a%b);
}
ll lcm(ll a,ll b){return a/gcd(a,b) * b;
}
int main()
{ll n,a,b,c;while(scanf("%lld%lld%lld%lld",&n,&a,&b,&c)!=EOF){ll ans=0;ans = n/a + n/b + n/c - n/lcm(a,b)- n/lcm(a,c)- n/lcm(b,c) + n/lcm(a,lcm(b,c));printf("%lld\n",ans);}return 0;
}

8.距离度量公式

  对于平面坐标上的两点(x1,y1)和(x2,y2):
(1)欧式距离计算公式:sqrt((x1-x2)(x1-x2)+(y1-y2)(y1-y2))
(2)曼哈顿距离计算公式:|x1-x2|+|y1-y2| 跟行列的计算顺序无关
例题:PIPIOJ1025: 最短距离(简单)

题目描述:
  小王和小明是好朋友,两人最开始各有一个初始位置 p 和一个恒定速度 v,从0时刻起开始,他们从初始位置以恒定速度开始行走,请告诉我行走过程中两人的最短距离是多少。

输入输出样例:

输入 :
第一行输入T代表测试样例数目。
对于每个样例,第一行包含四个整数 x1,y1,x2,y2,表示人的起点(x1,y1),(x2,y2)。
第二行是四个整数u1,v1,u2,v2,表示人的初始速度(u1,v1),(u2,v2)(分别为x轴和y轴方向的分速度)。
T <= 1000 , x1,y1,x2,y2,u1,v1,u2,v2的绝对值不大于1000。
输出: 对于每个样例,输出一行。“Case i: d”。i 代表案例编号,d代表答案,四舍五入到小数点后6位。
解释:
样例输入:
1
1 1 2 2
1 1 2 2
样例输出:
Case 1: 1.414214

  直接计算两个人的欧氏距离:小王:(x1+u1t,y1+v1t),小明:(x2+u2t,y2+v2t)

#include<bits/stdc++.h>
using namespace std;
int main()
{int T;scanf("%d",&T);int id=1;while(T--){double x1,x2,y1,y2,v1,v2,u1,u2,ans;scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);scanf("%lf%lf%lf%lf",&u1,&v1,&u2,&v2);// ans=sqrt((x1+u1*t-x2-u2*t)^2+(y1+v1*t-y2-v2*t)^2) // 整理得:ans = sqrt(((x1-x2)+(u1-u2)*t)^2+((y1-y2)+(v1-v2)*t)^2) // 化简       =[(u1-u2)^2+(v1-v2)^2]*t^2+ 2*((x1-x2)*(u1-u2)+(y1-y2)*(v1-v2))+(x1-x2)^2+(y1-y2)^2double a,b,c;a = (u1-u2)*(u1-u2)+(v1-v2)*(v1-v2);b = 2*((x1-x2)*(u1-u2)+(y1-y2)*(v1-v2));c = (x1-x2)*(x1-x2)+(y1-y2)*(y1-y2);if(a==0||-b/(2*a)<=0)ans=c;else ans = c-b*b/(4*a);printf("Case %d: %.6f\n",id++,sqrt(ans));}return 0;
}

9.中位数定理

  现在已知数轴上有n个点 x1,x2 … xn,如何找到一个点x,使得|x-x1|+|x-x2|+…+|x-xn| (或者是|x1-x|+|x2-x|+…+|xn-x|) 的值最小?
  答案:其实这个点x就是这些数的中位数。证明网上有很多,这里就不证明了
例题:PIPIOJ1018: 士兵排阵(中等)

题目描述:
  在一个划分成网格的操场上, n个士兵散乱地站在网格点上。 网格点由整数坐标(x,y)表示。士兵们可以沿网格边上、 下、 左、 右移动一步, 但在同一时刻任一网格点上只能有一名士兵。按照军官的命令,士兵们要整齐地列成一个水平队列,即排列成(x,y),(x+1,y),…,(x+n-1,y)。如何选择 x 和 y的值才能使士兵们以最少的总移动步数排成一列。 计算使所有士兵排成一行需要的最少移动步数。
输入

输入输出样例:

输入 :
多组测试用例。对于每一组测试用例,第1行是士兵数 n, 1≤n≤10000。 接下来 n行是士兵的初始位置, 每行有2个整数 x和 y,-10000≤x, y≤10000。
输出: 数据的输出为一行, 表示士兵排成一行需要的最少移动步数。
解释:
样例输入:
5
1 2
2 2
1 3
3 -2
3 3
样例输出:
8

  该题我们首先应该看出士兵在 x 轴和 y轴的移动是无关的(行列无关)。士兵只能横着移动和竖着移动,所以在 x 轴上的移动和 y 轴上的移动是无关的。所以我们对行列分开考虑。
  假设n个士兵的原始位置为 : (X1,Y1), (X2,Y2), (X3,Y3), (X4,Y4)… (Xn,Yn),士兵的最终位置为: (X,Y), (X+1,Y), (X+2,Y), (X+3,Y), (X+4,Y)… (X+n-1,Y)。
  对于y轴: 先对所有的Y坐标从小到大排序,排序后,为了方便描述,依然用Y1,Y2,Y3…Yn,Yi代表士兵的位置(已经排好序的),假如最后所有士兵都在y轴为Y的坐标上,则变成求|Y1-Y|+|Y2-Y|+|Y3-Y|+……|Yn-1-Y|+|Yn-Y|的最小值,根据中位数定理,我们知道 Y 取 Y1,Y2…Yn中位数时能够得到表达式的最小值。
  对于x轴: 先对所有的X坐标从小到大排序,排序后,为了方便描述,依然用X1,X2,X3…Xn,Xi代表士兵的位置(已经排好序的),最终士兵站的位置为X,X+1,X+2……X+n-1,那么即是求|X1-X|+|X2-(X+1)|+|X3-(X+2)|+……|Xn-(X+n-1)|的最小值。变形,即为|X1-X|+|(X2-1)-X|+|(X3-2)-X|+…+|(Xn-(n-1))-X|,利用中位数定理,X即为X1,X2-1,X3-2……Xn-(n-1)的中位数,据此可以求得X方向的最小移动步数。
  X轴方向移动步数和Y轴方向移动步数加起来即为最终结果。

#include<bits/stdc++.h>
using namespace std;
const int N=10003;
int x[N],y[N];
int main(){int n;while(scanf("%d",&n)!=EOF){int ans=0;for(int i=0;i<n;i++) scanf("%d%d",&x[i],&y[i]);sort(y,y+n);for(int i=0;i<n;i++) ans+=abs(y[i]-y[n/2]);sort(x,x+n);for(int i=0;i<n;i++) x[i]=x[i]-i;sort(x,x+n);for(int i=0;i<n;i++) ans+=abs(x[i]-x[n/2]);printf("%d\n",ans);}return 0;
}

每日古诗一首

如梦令·昨夜雨疏风骤 宋·李清照 昨夜雨疏风骤,浓睡不消残酒。试问卷帘人, 却道海棠依旧。知否,知否?应是绿肥红瘦。

——2023.03.23

渔家傲·秋思骤 宋·范仲淹 塞下秋来风景异,衡阳雁去无留意。 四面边生连角起,千嶂里,长烟落日孤城闭。 浊酒一杯家万里,燕然未勒归无计。 羌管悠悠霜满地,人不寐,将军白发征夫泪。

——2023.04.08

Leetcode刷题系列(一)——巧解数学问题相关推荐

  1. LeetCode刷题系列

    LeetCode 我们工作面试和提高自身数据结构和算法能力的时候往往需要刷刷题,我选择LeetCode是通过一个留学论坛了解的.专业,覆盖语种全面. 提前说说刷题的心得: 尽量手写代码,少使用IDE的 ...

  2. Leetcode刷题系列汇总

    文章目录 一.前言 二.分治 && 归并 三.BFS 四.DFS & 回溯 五.动态规划 六.贪心算法 七.二叉树 7.1 中序遍历 SQL 一.前言 ~~~~~~       ...

  3. LeetCode 刷题系列(前缀和题目)之 974. 和可被 K 整除的子数组

    题目: 给定一个整数数组 nums 和一个整数 k ,返回其中元素之和可被 k 整除的(连续.非空) 子数组 的数目. 子数组 是数组的 连续 部分. 示例 1: 输入:nums = [4,5,0,- ...

  4. LeetCode刷题系列-- 174. 地下城游戏

    一些恶魔抓住了公主(P)并将她关在了地下城的右下角.地下城是由 M x N 个房间组成的二维网格.我们英勇的骑士(K)最初被安置在左上角的房间里,他必须穿过地下城并通过对抗恶魔来拯救公主. 骑士的初始 ...

  5. LeetCode 刷题系列 -- 1110. 删点成林

    给出二叉树的根节点 root,树上每个节点都有一个不同的值. 如果节点值在 to_delete 中出现,我们就把该节点从树上删去,最后得到一个森林(一些不相交的树构成的集合). 返回森林中的每棵树.你 ...

  6. leetcode刷题(三)——容斥原理

    leetcode刷题系列三.这一节的内容主要是容斥原理的题目和题解. 百度百科上容斥原理的解释: 在计数时,必须注意没有重复,没有遗漏.为了使重叠部分不被重复计算,人们研究出一种新的计数方法,这种方法 ...

  7. 卷进大厂系列之LeetCode刷题笔记:二分查找(简单)

    LeetCode刷题笔记:二分查找(简单) 学算法,刷力扣,加油卷,进大厂! 题目描述 涉及算法 题目解答 学算法,刷力扣,加油卷,进大厂! 题目描述 力扣题目链接 给定一个 n 个元素有序的(升序) ...

  8. Leetcode-How-What 力扣Leetcode刷题指南

    Leetcode-How-What 力扣Leetcode刷题指南 About the way how to use Leetcode wisely for preparing the intervie ...

  9. 【Shell牛客刷题系列】SHELL5 打印空行的行号:一起学习grep命令搭配正则表达式的使用

    该系列是基于牛客Shell题库,针对具体题目进行查漏补缺,学习相应的命令. 刷题链接:牛客题霸-Shell篇. 该系列文章都放到专栏下,专栏链接为:<专栏:Linux>.欢迎关注专栏~ 本 ...

最新文章

  1. 服务器共享文件和电脑同步,云服务器共享文件夹同步
  2. centos 对已有卷扩容_CentOS LVM 新加硬盘,扩容逻辑卷步骤
  3. time zone issue in text processing
  4. linux将访问日志切成每天,最简单自动切割 nginx 访问日志示例
  5. python 最快 因式分解_Python实现的对一个数进行因式分解操作示例
  6. wordpress url index.php,WordPress对URL的路由解析过程详解
  7. MySQL 一张表中两个字段值互换
  8. 算法 Tricks(六)— if 条件分支的简化
  9. html怎样设置图片的圆角矩形,怎么把矩形变成圆角 ps怎么在原来的矩形中改成圆角...
  10. 郭天祥10天学会单片机笔记学习资料(1.1)
  11. 分布式部署OpenDevOps报502错问题解决全过程
  12. 排名第一的word模板引擎,到底有多神仙
  13. 破解Zip加密文件常用的几种方法
  14. [案例3-2]银行存取款程序设计
  15. 一线城市广州:全日制本科生参保即可落户
  16. 大一寒假培训(三)——暴力枚举及妙用
  17. RCS(Real-time control systems) 库
  18. 怎么制作搞笑的GIF
  19. Python练手项目:PDF小工具
  20. mysql分库分表取模扩容_MyCat分库分表策略——范围取模

热门文章

  1. golang在线词典
  2. 奇迹mu服务端开服架设技术搭建Data文件说明
  3. 类型转换神器Mapstruct新出的Spring插件真好用
  4. iOS开发 - UIPageControl实现分页图片轮播器
  5. 在CSDN写博客怎么粘贴有格式的代码?
  6. SCI检索报告证明下载
  7. js之ajax文件上传
  8. html textarea滚动条样式设置
  9. ThinkPHP5企业新闻管理系统
  10. 130. 火车进出栈问题