发现自己几何sb,还是总结一下
已知三点求圆心,但三点不能共线
Point Getcir(Point A,Point B,Point C){//给予三个点,求圆心。
double a = 2*(B.x - A.x);
double b = 2*(B.y - A.y);
double c = (B.x*B.x+B.y*B.y) - (A.x*A.x+A.y*A.y);
double d = 2*(C.x-B.x);
double e = 2*(C.y-B.y);
double f = (C.x*C.x + C.y*C.y) - (B.x*B.x + B.y*B.y);
double x = (b*f-e*c)/(b*d-e*a);
double y = (d*c-a*f)/(b*d-e*a);
double r = sqrt((x-A.x)*(x-A.x) + (y-A.y)*(y-A.y));
Point ans(x,y);
R = r;
return ans;
}
对于一个水平的数轴,其上有N个点找到一个点使其距离和最小,那么这个点是中位数那个点。。
如图
无论是奇数和点还是偶数个点,都相当于是两两配对。这种肯定是最佳的。注意千万不要误认为是平均值的点是最小的。应为选平均值,除非平均值是中位数,否则一定会在两两配对的基础上多个点到平均值的距离。可以画图看下。注意!~!
参考题:http://acm.henu.edu.cn/problem/problempage?id=1013
乘积最大定理:
把一个数拆分成多个不同的数相加,求他们的成绩最大值时,把这个数拆成从2开始的多个连续的数得到的乘积是最大的。
例题:http://acm.hdu.edu.cn/showproblem.php?pid=5976
组合数恒等公式
C
n
m
=
C
n
−
1
m
+
C
n
−
1
m
−
1
C_{n}^{m} = C_{n-1}^{m} + C_{n-1}^{m-1}
Cnm=Cn−1m+Cn−1m−1
利用这个公式可以对组合数进行打表
代码如下:
const int MAX = 3010;
typedef long long ll;
ll C[MAX][MAX];
void init(){
for(int i=0;i<=3000;++i){
C[i][0] = 1;
for(int j=1;j<=i;++j){
C[i][j] = C[i-1][j] + C[i-1][j-1];
}
}
}
海伦公式求三角形面积:
p
(
p
−
a
)
(
p
−
b
)
(
p
−
c
)
2
\sqrt[2]{p(p-a)(p-b)(p-c)}
2p(p−a)(p−b)(p−c)
其中p为半周长,a,b,c为三边的周长。
求正多边形的面积
因为是正多边形,所以我们可以通过把正N多边形分成N个等腰三角形。求出每个等腰三角形的面积,再乘以N即可。
首先我们可以求出
θ
=
P
I
/
N
θ = PI/N
θ=PI/N
这样
R
=
(
a
/
2
)
/
s
i
n
(
θ
)
R = (a/2)/sin(θ)
R=(a/2)/sin(θ)
即等腰三角形的高也可以求出
h
=
R
∗
c
o
s
(
θ
)
h = R*cos(θ)
h=R∗cos(θ)
故正多边形的总面积也可以算出
S
=
(
a
∗
h
)
/
2
∗
N
S = (a*h)/2*N
S=(a∗h)/2∗N
代码如下:
#include<bits/stdc++.h>
using namespace std;
const double PI = acos(-1.0);
double GetArea(int N,double A){
double Deg = PI/N;
double R = (A/2)/sin(Deg);
double H = R*cos(Deg);
double S = (A*H)/2*N;
return S;
}
对于从N个数里面选2个数,求出最大的最小公倍数
在正整数中,任意两个数互素的概率是 6/(π^2) = 0.608.,对于随机生成数的情况,我们直接枚举最大的100个数就能得到正确结果。
例如:https://www.nowcoder.com/acm/contest/144/J
从N个数里面选任意个数相加 向M取模,问你有多少中结果?
求出N个数和M这个数的最大公约数GCD,M/GCD就是结果的总数。
因为N个数任意相加最后结果一定会说她们最大公约数的倍数,加M是因为加0就相当于加M。
两个题目:http://codeforces.com/contest/1011/problem/E
https://www.nowcoder.com/acm/contest/160/A
排列组合的一个性质:
C
n
m
+
C
n
m
−
1
=
C
n
+
1
m
C_{n}^{m} + C_{n}^{m-1} = C_{n+1}^{m}
Cnm+Cnm−1=Cn+1m
对于N个线段覆盖的公共长度的求法
每个线段为l,r两个端点。那么N个线段的公共长度就是min® - max(l),即最小的右端点减去最大的左端点。如果为负数,表示不存在N个线段覆盖的端点。要注意思考啊。
参考题目:http://codeforces.com/contest/1029/problem/C
整除分块
∑
i
=
1
n
[
n
i
]
\sum_{i=1}^{n}[\frac{n}{i}]
i=1∑n[in]
就是求这个表达式的和,[]表示向下取整.对于向下取整的除法是存在一个区间除以这个区间数,结果都相同。比如x/i = 2,那么x /2,就是得到2的区间最后一个数。所以我们可以利用这个性质。按区间分块计算。如下:
ll res = 0,r = 0;
for(ll i=1;i<=x;i=r+1){
r = x/(x/i);//获得这个区间的最后一个数
res += (r-i+1)*(x/i);//用区间长度乘以结果
}
参考题目:https://www.nowcoder.com/acm/contest/158/A
再给N个区间,求被N-1个区间覆盖的最大距离或者是点
最近两场cf都碰到这个问题,这里总结一下,考虑把所有左端点和右端点全部存起来,放到两个multiset里面,然后扫描N个区间,每次把两个端点删去。如果左端点的最大值比右端点的最小值下,那么这个区间就符合被N-1个区间覆盖。最后再把两个端点插入进去。维护最大值就可以了。
这个想法也可以推广到二维的情况。维护左右x,上下y,每次扫描删除四个端点。最后再判断对应x,y是否符合。再插入进去。
两个题目:
http://codeforces.com/contest/1029
http://codeforces.com/contest/1028/problem/C
在N大于2的时候,奇数的和和偶数的和的gcd一定是大于一的,而且是最中间的那个数,如果是偶数就是N/2
因为中间那个数相当于是一个中心对称轴,两边的对应位置的数的和一定是中间那个数的倍数。
参考题目:
http://codeforces.com/contest/1038/problem/B
如果有N个东西,每个东西出现的概率是p[i],那么出现东西的个数期望就是sum p[1-N]
我们可以假设有两个物品啊,出现概率分别是A,B,那么出现个数为0,1,2;
p[0] = (1-A)(1-B);
p[1] = A(1-B)+(1-A)B = A-B+2AB
p[2] = AB
概率期望E = 0p[0] + 1p[1] + 2p[2]
合并后E = A+B;
参考题目:https://www.nowcoder.com/acm/contest/180/B
对于B进制数,快速判断某一位的数是多少
对于一个B进制的数s,我们想知道第i位的数字是多少,那么
int num = (s%(pw[i]*B))/pw[i];
就可以求得这个位的数,先对其高一位取膜,再向下取整除以这一位的幂,即可得到这一位的数字。
一个常用的整数向上取整
c
e
i
l
(
(
d
o
u
b
l
e
)
s
u
m
/
N
)
=
(
s
u
m
−
1
+
N
)
/
N
ceil((double)sum/N) = (sum-1+N)/N
ceil((double)sum/N)=(sum−1+N)/N
调用ceil需要转换成double,而后者可以直接在整数形式下向上取整.
gcd 辗转相减法 推广到求多个数
g
c
d
(
x
,
y
)
=
g
c
d
(
x
−
y
,
y
)
gcd(x,y) = gcd(x-y,y)
gcd(x,y)=gcd(x−y,y)
对于多个数
g
c
d
(
x
,
y
,
z
)
=
g
c
d
(
x
−
y
,
y
,
z
)
=
g
c
d
(
x
−
y
,
y
−
z
,
z
)
gcd(x,y,z) = gcd(x-y,y,z) = gcd(x-y,y-z,z)
gcd(x,y,z)=gcd(x−y,y,z)=gcd(x−y,y−z,z)
参考例题:https://codeforces.com/problemset/problem/1458/A