1、分数取模一般不直接取模,而是利用快速幂取模:
(a/b) %m= a*(b^(m-2))%m
2、组合数计算可以考虑用杨辉三角来求,比较容易理解。
3、找到某一个点使得其到其他点的距离尽可能小:
给定n个坐标,让你找一个位置,使得这n个点到它的距离和尽可能短(dis=abs(x1-x2)+abs(y1-y2)),可以将n个点分别按照横坐标,纵坐标排序,横纵坐标的中位数一定是最小的,因为如果不是中位数,假设这个点在两个数之外,则他到两点的距离和一定是两个点分别到他的距离和相加,但是如果它在这两个点中间,则距离为这两个点的距离,比刚才要小。如果是那种某个点走单位长度有权重w,可以看作w个点在这个位置,然后像之前一样找中点。
4、如何判断二进制下一个数是不是3的倍数:
按位来看,1在奇数位和偶数位的个数关系:abs(奇数位个数-偶数位个数)%3==0
5、如何判断一个数是不是11的倍数
用奇偶位差法,只要奇数位的和和偶数位的和的差值的绝对值是11的倍数(包括0),那这个数就是11的倍数。
6、具有偶数位的回文数一定不是质数,因为根据奇偶位差法,它一定是11的倍数,因此它一定不是是质数。
7、atan(y/x)仅仅求在两个象限内的值
atan2(y,x)求在四个象限内的值
8、数论分块
数论分块可以比较快速的求出整除的和。
面对这样一个问题
可以选择用O(n)的复杂度去暴力求解,但我们可以发现n/i的值在某一段中是相等的,比方说5/ 3, 5/ 4 ,5/5的大小都为1,所以可以用这一段的长度Len 乘以这一段的值就是可以快速求和。
面对这样一个问题
可以选择用O(n)的复杂度去暴力求解,但我们可以发现n/i的值在某一段中是相等的,比方说5/ 3, 5/ 4 ,5/5的大小都为1,所以可以用这一段的长度Len 乘以这一段的值就是可以快速求和。从而将O(n)优化到O(sqrt(n))。
代码:
int ans = 0;
for(int l = 1, r = 0; l <= n; l = r + 1) {
r = n / (n / l); // 求区间的右端,这是一个数学规律
ans += (r - l + 1) * (n / l);
}
数论分块往往隐藏在一些数学公式中,如求模等,需要将其进行处理后才能应用数论分块。
数论分块例题:
浙江省赛F例题
解析
在确定了n之后,m就唯一确定,因为m只能增加,所以离m最近的地方一定是
⌈
m
n
−
x
⌉
∗
(
n
−
x
)
\lceil \frac{m}{n-x}\rceil*(n-x)
⌈n−xm⌉∗(n−x),m如果是n-x的倍数,则这个数恰好也是n-x的倍数,如果不是n-x的倍数,则必须是向上取整之后乘于(n-x),如果是向下取整则得到的数有可能比m小,是不符合题意的。
9、向上取整转化为向下取整:
⌈
m
n
⌉
=
⌊
m
−
1
n
⌋
+
1
\lceil \frac{m}{n}\rceil =\lfloor \frac{m-1}{n} \rfloor +1
⌈nm⌉=⌊nm−1⌋+1
10、求n的阶乘中某个因子的数量
n!可以写为
n
!
=
(
k
∧
m
)
∗
(
m
!
)
∗
a
n !=\left(k^{\wedge} m\right)^{*}(m !)^{*} a
n!=(k∧m)∗(m!)∗a 其中k是该因子,m=n/k,a为不含k的乘积。
n!=n*(n-1)(n-2)……321
=(k * 2k * 3k * mk) * a a是不含因子k的数的乘积,显然m=n/k;
=(k^m) * (1 * 2 * 3… * m) * a
=k^m * m! * a
接下来按照相同的方法可以求出m!中含有因子k的个数。