a[la+1]=0;
b[lb]=0;
for(i=la-1,j=lb-1;i>=0;i--,j--)
{if(a[i]=='.'){a[i+1]='.';continue;}
sum+=a[i]-'0';if(j>=0)sum+=b[j]-'0';
a[i+1]=sum%10+'0';sum/=10;
}
if(sum)a[0]=sum+'0';
elsestrcpy(a,&a[1]);
quw0(a);//根据题目需要是否保留尾0
}
二.计算几何:
1.线段相交:
intxj(pointx1,pointx2,pointx3,pointx4)//相交为1,不交为0
{
if(min(x1.x,x2.x)>max(x3.x,x4.x)||min(x1.y,x2.y)>max(x3.y,x4.y)
||min(x3.x,x4.x)>max(x1.x,x2.x)||min(x3.y,x4.y)>max(x1.y,x2.y)
)
return0;//不交:
矩形排斥实验,最小的>最大的肯定不交
inta,b,c,d;
a=(x1.x-x2.x)*(x3.y-x1.y)-(x1.y-x2.y)*(x3.x-x1.x);//跨立实验
b=(x1.x-x2.x)*(x4.y-x1.y)-(x1.y-x2.y)*(x4.x-x1.x);
c=(x3.x-x4.x)*(x1.y-x3.y)-(x3.y-x4.y)*(x1.x-x3.x);
d=(x3.x-x4.x)*(x2.y-x3.y)-(x3.y-x4.y)*(x2.x-x3.x);
returna*b<=0&&c*d<=0;
}
2.点关于直线的对称点:
点:
(a,b),直线:
Ax+By+C=0
#include
intmain()
{
intn;
floata,b,A,B,C,a1,b1;
scanf("%d\n",&n);
while(n--)
{scanf("%f%f%f%f%f",&a,&b,&A,&B,&C);
inta1=int(a-2*A*(A*a+B*b+C)/(A*A+B*B));
intb1=int(b-2*B*(A*a+B*b+C)/(A*A+B*B));
printf("%d%d\n",a1,b1);
}
}
3.求凸包
//根据题目改动数据类型,数组大小,排序方式
#include
#defineeps1e-8
structpoint
{
intx,y;
};
pointpnt[100003],res[100005];
booloperator<(pointA,pointB)//按y排也可,具体看题目要求
{returnA.xdoublemult(pointp0,pointp1,pointp2)
{return(p1.x-p0.x)*(p2.y-p0.y)-(p1.y-p0.y)*(p2.x-p0.x);}
//数组下标从0开始,n是点的个数,选中的点在保存在res数组中,个数是top
intgraham(pointpnt[],intn,pointres[])//选中的点在保存在res数组中,个数是top
{inti,len,k=0,top=1;
sort(pnt,pnt+n);//用cmp可能超时,原因未知
if(n==0)return0;res[0]=pnt[0];
if(n==1)return1;res[1]=pnt[1];
if(n==2)return2;res[2]=pnt[2];
for(i=2;i{while(top&&mult(pnt[i],res[top],res[top-1])<=eps)top--;
res[++top]=pnt[i];
}
len=top;res[++top]=pnt[n-2];
for(i=n-3;i>=0;i--)
{while(top!
=len&&mult(pnt[i],res[top],res[top-1])<=eps)top--;
res[++top]=pnt[i];
}
returntop;//返回凸包中点的个数
}
4.多边形面积
//点必须是顺时针给出或逆时针给出才可用此法
//使用时注意数据类型,和数据大小
structpoint{intx,y;}a[105];
intduo(pointa[],intn)//点在数组a[]中,个数是n
{inti,s=0;
for(i=1;i<=n;i++)
s+=(a[i-1].x*a[i%n].y-a[i-1].y*a[i%n].x);
if(s<0)s=-s;
returns;
//if(s%2)cout<
//elsecout<
}
5.皮克定理:
//S=a+b÷2-1
//(其中a表示多边形内部的点数,b表示多边形边界上的点数,S表示多边形的面积)
#include
structpoint
{
intx,y;
};
intgcd(intm,intn)
{
if(n==0)returnm;
returngcd(n,m%n);
}
intbian(pointa[],intn)//算出点A和点B组成的线段上的点
{ints=0,i;
for(i=1;i<=n;i++)
s+=gcd(abs(a[i-1].x-a[i%n].x),abs(a[i-1].y-a[i%n].y));
returns;
}
intduo(pointa[],intn)//求n边形的面积,注意ans未除2;
{
inti,s=0;
for(i=1;i<=n;i++)
s+=(a[i-1].x*a[i%n].y-a[i-1].y*a[i%n].x);
if(s<0)s=-s;
returns;
}
6.三角形:
1)点和三角形的关系
//注意数据类型
#include
structpoint{intx,y;};
booloperator==(pointA,pointB){returnA.x==B.x&&A.y==B.y;}
intarea(pointA,pointB,pointC)//三角形面积,未除2
{
ints=abs((B.x-A.x)*(C.y-A.y)-(B.y-A.y)*(C.x-A.x));
returns;
}
intpan3(pointa[],pointp)//若点在三角形内(不含边界),返回1;
{
intsa,sb,sc,s;
s=area(a[0],a[1],a[2]);
sa=area(a[0],a[1],p);
sb=area(a[0],a[2],p);
sc=area(a[1],a[2],p);
if(sa&&sb&&sc&&s==sa+sb+sc)return1;
if((!
sa||!
sb||!
sc)&&s==sa+sb+sc)
{
if(p==a[0]||p==a[1]||p==a[2])return4;//若点在三角形顶点上,返回4。
return3;//若点在三角形边界上(不含顶点),返回3;
}
return2;//若点在三角形外(不含边界),返回2;
}
2)三角形各种面积算法:
(1)已知三点坐标:
structpoint{doublex,y;};
doublearea(pointA,pointB,pointC)//三角形面积,未除2
{
doubles=abs((B.x-A.x)*(C.y-A.y)-(B.y-A.y)*(C.x-A.x));
returns/2;
}
(2)已知三条边和外接圆半径,公式为s=a*b*c/(4*R)
doubleGetArea(doublea,doubleb,doublec,doubleR)
{returna*b*c/4/R;}
(3)已知三条边和内接圆半径,公式为s=pr
doubleGetArea(doublea,doubleb,doublec,doubler)
{returnr*(a+b+c)/2;}
(4)已知三角形三条边,求面积
doubleGetArea(doulea,doubleb,doublec)
{
doublep=(a+b+c)/2;
returnsqrt(p*(p-a)*(p-b)*(p-c));
}
7.两圆相交面积
#include
#include
#include
usingnamespacestd;
#defineN3.14159265354
intmain()
{
doublen,a,b,c,d,r,l,i,j,t,s1,s2;
while(cin>>a>>b>>r>>c>>d>>l)
{
t=sqrt((a-c)*(a-c)+(b-d)*(b-d));
i=acos((t*t+r*r-l*l)/(2*t*r));
j=acos((t*t-r*r+l*l)/(2*t*l));
if(t<=max(l,r)-min(l,r))cout<elseif(t>=r+l)cout<<0.000<else
{
s1=N*r*r*2*i/(2*N)-(sin(2*i)*r*r)/2;
s2=N*l*l*2*j/(2*N)-(sin(2*j)*l*l)/2;
cout<}
}
}
三.搜索:
1.DFS(深度优先、回溯)
//根据题目意思,更改代码,深度可能超时,注意使用记忆式优化
voiddfs(intcur)//回溯
{
if(cur==n+1)output();//选好了所有的数
else
for(inti=1;i<=n;i++)//表示cur可以选1到n
if(!
bz[i])//没有用过就做
{
a[cur]=i;
bz[i]=true;//表示i已经用了
f(cur+1);
bz[i]=false;//把i置为没有用过,供下一次使用
}
}
2.BFS(广度优先)
//适合最少步数问题
//但不适合多情况步数问题(step+1和step+2)
structpoint
{
intx,y,step;
}s,e;
queueq;
chara[200][200];
intm,n,bz[200][200],h[8][2]={-2,-1,-2,1,2,-1,2,1,-1,-2,1,-2,-1,2,1,2};
intBFS(points)
{pointt,tt;
inti,j,x,y;
while(!
q.empty())q.pop();
q.push(s);bz[s.x][s.y]=1;
while(!
q.empty())
{
t=q.front();q.pop();
for(i=0;i<8;i++)
{
x=t.x+h[i][0];y=t.y+h[i][1];
if(x==e.x&&y==e.y)returnt.step+1;//到达结束标志
if(x>=0&&x=0&&y{
tt.x=x;tt.y=y;tt.step=t.step+1;
bz[x][y]=1;
q.push(tt);
}
}
}
}
四.数论:
1.最大公约数,最小公倍数:
intgcd(inta,intb)//公约数
{
if(b==0)returna;
returngcd(b,a%b);
}
intd=a/gcd(a,b)*b;//公倍数,注意一定要先除再乘,否则溢出
2.欧几里德扩展:
//ax+by=Gcd(a,b)解一定存在;ax+by=c时,当c%gcd(a,b)==0有解
intexgcd(inta,intb,int&x,int&y)
{
if(b==0){x=1;y=0;returna;}
intr=exgcd(b,a%b,x,y);
intt=x;
x=y;
y=t-a/b*y;
returnr;
}
3.大数除法求余、快速幂取余:
#include
usingnamespacestd;
voidxxa(chars[],longlong&a,longlongc)//a=大数s[]%c
{
inti=0;a=0;
while(s[i])
{
a=a*10+s[i++]-'0';
a%=c;
}
}
//若a在64位内可直接套用,否则先调用xxa()