郑州集训Day3

郑州集训Day3

主要加强了一下线性代数(数论应该没什么问题,就是知道MR有时是不靠谱的,还有筛法的复杂度是O(nlogn))
知道N阶行列式没有多项式求法(这里还要举行加强,比如O(n2)的求解线性方程组的方法)
然后向山大附中的同学借《组合数学》看了Polya计数法,这个比较得意,因为这个貌似比较难。
然后就是计算几何,模板才写了大概一半。

最新更新//2.4    加入了求平面点集的凸包的两个算法
计算几何模板
#include<cstdio>
#include
<cstring>
#include
<cmath>
#include
<cstdlib>
    
double inline max(double a,double b){return a>b?a:b;}
    
double inline min(double a,double b){return a<b?a:b;}
//计算几何模板
//二维 
//为了方便分离使用,函数尽量不调用其他函数
//基本函数:cross 
    const int N=100002
    
const double zero=1e-8;//1e-8 
    const double maxnum=1e8;
    
const double pi=3.1415926535;
    
const double du=3.1415926535/180;
    
    typedef 
struct {double x,y;}point;
    typedef 
struct {point a,b;}segment;
    typedef 
struct {double x,y;}Ds;//directed segment  
    typedef struct {point cl;double r;}cicle;
    typedef 
struct {point a,b,c,d;}Rect;//
    typedef struct {point a,b;}rect;//平行于坐标轴 ,左下右上
    /**//*
    BUG 1:输出时有时会输出-0.0000000 :输出时统一处理吧@#$%&^$#%@!#%@#!@# 
    
*/


    
//*************************Point*************************//
    double dis(point a,point b){return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}
    point symetrical(point a,point b)
{point c;c.x=b.x*2-a.x;c.y=b.y*2-a.y;return c;} //a关于b对称 
    point symetrical2(point a,point b,point c); //a关于直线bc对称 
    point symetrical2_fxy(point p,double a,double b,double c);//给出直线的解析式 
    bool online(point a,point b,point c){return (fabs(dis(a,b)+dis(a,c)-dis(b,c))<zero);}// 判定a在线段bc上
    double disline(point a,point b,point c);//求点到线段的最短距离 
    double disline2(point a,point b,point c);//求点到直线的最短距离 
    double disline2_fxy(point p,double a,double b,double c){return fabs(a*p.x+b*p.y+c)/sqrt(a*a+b*b);} 
    
    
//*************************Directed segment*************************//    
    Ds addDs(Ds a,Ds b){Ds c;c.x=a.x+b.x;c.y=a.y+b.y;return c;}
    Ds rotateDs(Ds a,
double A) {Ds c;c.x=a.x*cos(A)-a.y*sin(A);c.y=a.x*sin(A)+a.y*cos(A);return c;}//右旋 
    double dotDS(Ds a,Ds b){return a.x*b.x+a.y*b.y;} 
    
double crossDS(Ds a,Ds b){return a.x*b.y-a.y*b.x;} 
    
double cross(point a,point b,point c){return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y);}//   ab ×ac 
    bool intersect(point a,point b,point c,point d){return((cross(a,b,c)*cross(a,b,d)<-zero)
    
/**//*若判断线段和直线是否相交,则更简单,线段跨立直线即可*/&&(cross(c,d,a)*cross(c,d,b)<-zero));}

    point poi(point a, point b, point c, point d)
{double s1,s2;point p;s1=cross(a,b,c);s2=cross(a,b,d);
    
/**//*求线段的交点*/  /**//*求证明!*/     p.x=(c.x*s2-d.x*s1)/(s2-s1);p.y= (c.y*s2-d.y*s1)/(s2-s1);return p;}

 
    
//*************************Integrated skill*************************//  
    double area(int n,point p[N]){double s=p[n].x*p[1].y-p[1].x*p[n].y;//这里实际上是叉乘 
                                n--;for(;n;n--)s+=p[n].x*p[n+1].y-p[n+1].x*p[n].y;return fabs(s)/2;}
//
/**//**/bool inarea(point a,int n,point p[N]);//判断点是否在多边形内 
/**//**/bool Linarea(point a,int n,point p[N]);//判断线段是否在多边形内 /*未开发*/ /*极难*/ 
    cicle Outcicle(point a,point b,point c); /**//*未开发*/
    cicle Incicle(point a,point b,point c);  
/**//*未开发*/
                            
    
//********************************Convex hull******************************//
    point p[N];
    point q[N];
    
int ans[N];
    
bool visit[N];
    
int n,m,ss;
    
int t; 
    
int num[N];
    
int a[N];
    
//Jarvis T=O(NM),M为凸包上的点数 
    void Jarvis();
    
void Search(int s);
    
bool ok(int i,int j,int k);
    
//Graham() T=O(NlogN) 
    void Graham();
    
void Qsort(int low,int high);
    
int Cross(point a,point b,point c);
    
void inline Change(int i,int j){point t=p[i];p[i]=p[j];p[j]=t;}
    
    
int main(){
        
//Jarvis();
        
//Graham();
        }
 
     
bool inarea(point a,int n,point p[N]){
            
int count=false;
            point t;t.x
=-maxnum;t.y=a.y;//t:a左侧的无穷远处
            p[n+1]=p[1];
            
for(int i=1;i<=n;i++{
                
if(online(a,p[i],p[i+1]))
                    
return true;
                
if(p[i].y==a.y&&p[i].x<a.x){//点在射线上,注意不要写成了直线。
                    if(p[i].y==max(p[i].y,p[i+1].y))
                        count
^=1
                    }
 
                
else if(p[i+1].y==a.y&&p[i+1].x<a.x)
                     
if(p[i+1].y==max(p[i].y,p[i+1].y))
                        count
^=1
                     }
 
                
else if((cross(p[i],p[i+1],a)*cross(p[i],p[i+1],t)<-zero)//线段相交 
                            &&(cross(a,t,p[i])*cross(a,t,p[i+1])<-zero))
                    count
^=1
                }

            
return count;
            }
 
    
double disline(point a,point b,point c){//用解析法求垂足,再分类讨论 
            point d;
            
if(c.x==b.x){//斜率为∞ 
                if((a.y-b.y)*(a.y-c.y)<-zero)
                    
return fabs(a.x-b.x);
                
else
                    
return min(dis(a,b),dis(a,c)); 
                }
 
            
double k=(c.y-b.y)/(c.x-b.x);
            d.x
=(k*k*b.x+k*(a.y-b.y )+a.x)/(k*k+1);
            d.y
=k*(d.x-b.x)+b.y;
            
if(online(d,b,c))
               
return dis(a,d);
            
else
               
return min(dis(a,b),dis(a,c)); 
            }

    
double disline2(point a,point b,point c){//利用d=|Ax+By+C|/sqrt(A^2+B^2) 结果化简版,不需判定斜率 
            double x1,y1,x2,y2,d;
            x1
=c.x-b.x;
            y1
=c.y-b.y;
            x2
=a.x-b.x;
            y2
=a.y-b.y;
            
return fabs(x1*y2-x2*y1)/sqrt(x1*x1+y1*y1);
            }

    point symetrical2(point a,point b,point c)
{//用解析法求垂足,再做对称 
            point d,q;
            
if(b.x==c.x){//斜率为∞
                q.x=b.x+c.x-a.x;
                q.y
=a.y; 
                
return q; 
                }
 
            
double k=(c.y-b.y)/(c.x-b.x); 
            d.x
=(k*k*b.x+k*(a.y-b.y )+a.x)/(k*k+1);
            d.y
=k*(d.x-b.x)+b.y;
            q
=symetrical(a,d);
            
return q; 
            }

    point symetrical2_fxy(point p,
double a,double b,double c){//__解析式版 结果化简版,不需判定斜率
            point q;
            q.x
=((b*b-a*a)*p.x-2*a*b*p.y-2*a*c)/(b*b+a*a); 
            q.y
=((a*a-b*b)*p.y-2*a*b*p.x-2*b*c)/(b*b+a*a); 
            
return q; 
            }
 
    
void Jarvis(){
        freopen(
"graham.in","r",stdin); 
        freopen(
"graham.out","w",stdout);
        scanf(
"%d",&n);
        
for(int i=1;i<=n;i++)
            scanf(
"%lf %lf",&p[i].x,&p[i].y); 
        fclose(stdin);
        m
=1;
        
for(int j=2;j<=n;j++)
            
if((p[j].y<p[m].y)||(p[j].y==p[m].y&&p[j].x<p[m].x))
                m
=j;//找距离最近的点 
        memset(visit,false,sizeof(visit));
        ss
=1;
        ans[
1]=m;
        Search(m);
//搜索下一个在凸包上的点 
        printf("%d\n",ss);
        
for(int j=1;j<=ss;j++)
            printf(
"%.0lf %.0lf\n",p[ans[j]].x,p[ans[j]].y);
        fclose(stdout);
        }
 
    
void Search(int s){
        
int i,j,k;
        
for(i=1;i<=n;i++)
            
if(false==visit[i]&&i!=s) //找还没有判定的点,也不是正在判定的s 
                 break
        k
=i;
        
for(j=i+1;j<=n;j++)//寻找可判定的点 
            if(false==visit[j]&&j!=s&&ok(s,k,j))k=j;
        visit[k]
=true;
        
if(k!=m){//记录,判定下一个 
            ss++;
            ans[ss]
=k;
            Search(k);
            }
 
        }

    
bool ok(int i,int j,int k){
        
double cha=cross(p[i],p[j],p[k]); 
        
double len1=dis(p[i],p[j]);
        
double len2=dis(p[i],p[k]);
        
if(cha<-zero)//在内部 
            return true;
        
else if(fabs(cha)<zero&&len2>len1)//在边上选择更远的点 
                return true;
             
else
                
return false;
        }
 
    
void Graham(){
        freopen(
"graham.in","r",stdin); 
        freopen(
"graham.out","w",stdout);
        scanf(
"%d",&n);
        
for(int i=1;i<=n;i++){
            scanf(
"%lf %lf",&p[i].x,&p[i].y);
            num[i]
=i;
            }
 
        fclose(stdin); 
        
int ii=1;
        
for(int i=2;i<=n;i++)
            
if(p[i].y<p[ii].y||(p[i].y==p[ii].y&&p[i].x<p[ii].x))//选择一个必定在凸包上的点 
                ii=i;
        Change(
1,ii);
        Qsort(
2,n);
        
int t=1;
        a[
1]=1;
        a[
2]=2;
        a[
3]=3;
        t
=3;
        
for(int i=4;i<=n;i++){//模拟栈 
            while(Cross(p[a[t-1]],p[a[t]],p[i]))t--;
            t
++;a[t]=i;
            }

        printf(
"%d\n",t);
        
for(int i=1;i<=t;i++)
            printf(
"%.0lf %.0lf\n",p[a[i]].x,p[a[i]].y);
        fclose(stdout);
        }

    
int inline Cross(point a,point b,point c){
            
if(cross(a,b,c)<-zero||(fabs(cross(a,b,c)))<zero&&dis(a,b)<dis(a,c)) 
                
return true;
            
else return false
            }

    
void Qsort(int low,int high){
        
if(low==high)return;
        Qsort(low,(low
+high)/2);
        Qsort((low
+high)/2+1,high);
        
int a=low,b=(low+high)/2+1;
        
for(int i=low;i<=high;i++){
            
if(Cross(p[1],p[a],p[b])&&b<=high||a>(low+high)/2){
                q[i]
=p[b];
                b
++;
                }

            
else{
                q[i]
=p[a];
                a
++;
                }

            }

        
for(int i=low;i<=high;i++)
            p[i]
=q[i];
        }

    
    
/**//*公式
S=a*h/2          (底*高/2)
S=a*b*sinC/2  (两边和夹角)
S=sqrt(p*(p-a)*(p-b)*(p-c)) p=(a+b+c)/2
  (已知3边长)
S=a*b*c/(4R)      (已知3边长和外接圆半径R)
S=(a+b+c)/(2r)    (已知3边长和内接圆半径r)
S=|cross(A,B,C)|/2  (叉积的一半)

INcicle
半径r=S/p=2S/(a+b+c)
圆心
对于三角形ABC,cross(A,B,C)>0
将有向线段AB逆时针旋C/2度,得到线段seg1
将有向线段CB逆时针旋A/2度,得到线段seg2
圆心就是seg1和seg2的交点
*/
 

/**//*三维 (未整理)
double cross(point a,point b,point c)
{ point p;
   p.x = a.y*b.z-a.z*b.y;
   p.y=a.z*b.x-a.x*b.z;
   p.z=a.x*b.y-a.y*b.x;
  return(sqrt(p.x*p.x+p.y*p.y+p.z*p.z)
}
*/




你可能感兴趣的:(郑州集训Day3)