排列组合
圆排列
有限多重集的排列 n!/(n1!*n2!*...*nk!)
n元无限集可重-r组合C(n+r-1,r)种。
n元无限集取r个,n中每个至少出现一次C(r-1,n-1)(r≥n)
直线分平面:
f(1) = 2
f(n) = f(n-1)+n = n(n+1)/2+1
折线分平面:
f(1) = 2
f(n) = f(n-1)+4(n-1)+1 = 2n^2-n+1
圆分平面:
f(1) = 2
f(n) = f(n-1)+2(n-1) = n^2-n+2
三角形分平面:
f(1) = 2
f(n) = f(n-1)+6*(n-1)
平面分空间:
f(1) = 2
g(n) = n(n+1)/2+1
f(n) = f(n-1)+g(n-1) = (n^3+5n)/6+1
已知p1(x1,x1),p2(x2,y2),求Ax+By+C = 0
A = y2 - y1
B = x1 - x2
C = x2*y1-x1*y2
海伦公式
, p为半周长
四边形最大面积
斯特林公式:
n很大时,
笛卡尔定理
4个圆相切,外切k = 1/r,内切k = -1/r,圆退化成直线k = 0。
一个长度为n-2的Purfer序列唯一对应一个n个点的树,且Purfer序列中i出现的次数就是节点i的度数减一。
全面积为πa2的圆锥最大面积为sqrt(2)/12*πa^3。
正弦定理sinA / a = sinB / b = sinC/c
余弦定理a2 = b2 + c2- 2bc·cosA
正切定理(a+b)/(a-b) = tan[(A+B)/2]/tan[(A-B)/2]
多边形面积
如果逆时针给出点坐标,值为正,
如果顺时针给出点坐标,值为负。
Bash游戏:
有一堆石子共有N个。A B两个人轮流拿,A先拿。每次最少拿1颗,最多拿K颗,拿到最后1颗石子的人获胜。
若n不足k+1,则A第一次取完,A胜。
若n是k+1的倍数,每次A取x,B都能取k+1-x,B胜。
否则,A胜。
威佐夫游戏:
有2堆石子。A B两个人轮流拿,A先拿。每次可以从一堆中取任意个或从2堆中取相同数量的石子,但不可不取。
两堆石头x < y,若(y-x)*(sqrt(5)+1) / 2+1) == x,则B胜。否则A胜。
1/a循环节长度:
a先约去2和5的因子->b,然后球欧拉函数值?,求一个最小的x,使得x|?且10^x%b == 1。
struct node { int x,y; friend bool operator <(node a,node b) { if(a.x == b.x) return a.y<b.y; return a.x<b.x; } }a[1005],ans[1005]; int n,m,l; int cross(node a,node b,node c)//向量积 { return (a.x-c.x)*(b.y-c.y)-(b.x-c.x)*(a.y-c.y); } int convex(int n)//求凸包上的点 { sort(a,a+n); int m = 0; //求得下凸包,逆时针 //已知凸包点m个,如果新加入点为i,则向量(m-2,i)必定要在(m-2,m-1)的逆时针方向才符合凸包的性质 //若不成立,则m-1点不在凸包上。 for(int i = 0;i < n;i++) { while(m > 1 && cross(ans[m-1],a[i],ans[m-2])<=0) m--; ans[m++] = a[i]; } int k = m; //求得上凸包 for(int i = n-2;i >= 0;i--) { while(m > k && cross(ans[m-1],a[i],ans[m-2])<=0) m--; ans[m++] = a[i]; } if(n > 1) m--;//起始点重复。 return m; }
求凸包
double x1,x2,x3,x4,y1,y2,y3,y4; bool f() { double t1 = (x2-x1)*(y3-y2)-(x3-x2)*(y2-y1); double t2 = (x2-x1)*(y4-y2)-(x4-x2)*(y2-y1); double t3 = (x4-x3)*(y1-y4)-(x1-x4)*(y4-y3); double t4 = (x4-x3)*(y2-y4)-(x2-x4)*(y4-y3); if(t1*t2 <= 0 && t3*t4 <= 0) return 1; else return 0; } int main() { int T; scanf("%d",&T); while(T--) { scanf("%lf%lf%lf%lf%lf%lf%lf%lf",&x1,&y1,&x2,&y2,&x3,&y3,&x4,&y4); if(f()) printf("Yes\n"); else printf("No\n"); } return 0; }
判断线段相交
int x1,x2,x3,x4,y1,y2,y3,y4,z1,z2,z3,z4; bool f() { int a11 = x1-x2,a12 = x2-x3,a13 = x3-x4; int a21 = y1-y2,a22 = y2-y3,a23 = y3-y4; int a31 = z1-z2,a32 = z2-z3,a33 = z3-z4; if(a11*a22*a33+a12*a23*a31+a13*a21*a32-a13*a22*a31-a11*a23*a32-a12*a21*a33 == 0) return 1; else return 0; } int main() { int T; scanf("%d",&T); while(T--) { scanf("%d%d%d%d%d%d%d%d%d%d%d%d",&x1,&y1,&z1,&x2,&y2,&z2,&x3,&y3,&z3,&x4,&y4,&z4); if(f()) printf("Yes\n"); else printf("No\n"); } return 0; }
判断四点公面
double XX,YY,R,X1,X2,X3,Y1,Y2,Y3; bool f() { double a1 = (X1-XX)*(X1-XX)+(Y1-YY)*(Y1-YY); double a2 = (X2-XX)*(X2-XX)+(Y2-YY)*(Y2-YY); double a3 = (X3-XX)*(X3-XX)+(Y3-YY)*(Y3-YY); double rr = R*R; if(a1 < rr-1e-6 && a2 < rr-1e-6 && a3 < rr-1e-6) return 1; if(a1 > rr+1e-6 && a2 > rr+1e-6 && a3 > rr+1e-6) { double t = ((XX-X1)*(X2-X1)+(YY-Y1)*(Y2-Y1))*((XX-X2)*(X1-X2)+(YY-Y2)*(Y1-Y2)); if(t > 1e-6) { t = abs((X1-XX)*(Y2-YY)-(X2-XX)*(Y1-YY))/sqrt((X1-X2)*(X1-X2)+(Y1-Y2)*(Y1-Y2)); if(t*t < rr+1e-6) return 0; } t = ((XX-X3)*(X2-X3)+(YY-Y3)*(Y2-Y3))*((XX-X2)*(X3-X2)+(YY-Y2)*(Y3-Y2)); if(t > 1e-6) { t = abs((X3-XX)*(Y2-YY)-(X2-XX)*(Y3-YY))/sqrt((X3-X2)*(X3-X2)+(Y3-Y2)*(Y3-Y2)); if(t*t < rr+1e-6) return 0; } t = ((XX-X3)*(X1-X3)+(YY-Y3)*(Y1-Y3))*((XX-X1)*(X3-X1)+(YY-Y1)*(Y3-Y1)); if(t > 1e-6) { t = abs((X3-XX)*(Y1-YY)-(X1-XX)*(Y3-YY))/sqrt((X3-X1)*(X3-X1)+(Y3-Y1)*(Y3-Y1)); if(t*t < rr+1e-6) return 0; } return 1; } return 0; } int main() { int T; scanf("%d",&T); while(T--) { scanf("%lf%lf%lf%lf%lf%lf%lf%lf%lf",&XX,&YY,&R,&X1,&Y1,&X2,&Y2,&X3,&Y3); if(f()) printf("No\n"); else printf("Yes\n"); } return 0; }
判断圆和三角形是否相交