ACM常用代码
作者:互联网
ACM小组内部预定函数
Ver 2.0 by IcyFenix
数学问题: |
|
|
|
2.精度计算——乘法(大数乘小数) |
|||
|
|
|
|
字符串处理: |
|
|
|
|
|||
|
|
|
|
计算几何: |
|
|
|
|
|
|
|
数论: |
|
|
|
|
|||
|
|
|
|
图论: |
|
|
|
|
|
|
|
排序/查找: |
|
|
|
|
|
|
|
数据结构: |
|
|
|
|
|
|
一、数学问题
1.精度计算——大数阶乘
语法:int result=factorial(int n); |
|
参数: |
|
n: |
n 的阶乘 |
返回值: |
阶乘结果的位数 |
注意: |
|
|
本程序直接输出n!的结果,需要返回结果请保留long a[] |
|
需要 math.h |
源程序: |
|
|
int factorial(int n) a[0]=1; |
2.精度计算——乘法(大数乘小数)
语法:mult(char c[],char t[],int m); |
|
参数: |
|
c[]: |
被乘数,用字符串表示,位数不限 |
t[]: |
结果,用字符串表示 |
m: |
乘数,限定10以内 |
返回值: |
null |
注意: |
|
|
需要 string.h |
源程序: |
|
|
void mult(char c[],char t[],int m) for (i=0;i<l;i++) for (i=0;i<l;i++) |
3.精度计算——乘法(大数乘大数)
语法:mult(char a[],char b[],char s[]); |
|
参数: |
|
a[]: |
被乘数,用字符串表示,位数不限 |
b[]: |
乘数,用字符串表示,位数不限 |
t[]: |
结果,用字符串表示 |
返回值: |
null |
注意: |
|
|
空间复杂度为 o(n^2) |
|
需要 string.h |
源程序: |
|
|
void mult(char a[],char b[],char s[]) for (i=0;i<alen;i++) for (i=alen-1;i>=0;i--) for (i=blen-2;i>=0;i--) for (i=0;i<k;i++) result[i]+='0'; while(1) |
4.精度计算——加法
语法:add(char a[],char b[],char s[]); |
|
参数: |
|
a[]: |
被乘数,用字符串表示,位数不限 |
b[]: |
乘数,用字符串表示,位数不限 |
t[]: |
结果,用字符串表示 |
返回值: |
null |
注意: |
|
|
空间复杂度为 o(n^2) |
|
需要 string.h |
源程序: |
|
|
void add(char a[],char b[],char back[]) |
5.精度计算——减法
语法:sub(char s1[],char s2[],char t[]); |
|
参数: |
|
s1[]: |
被减数,用字符串表示,位数不限 |
s2[]: |
减数,用字符串表示,位数不限 |
t[]: |
结果,用字符串表示 |
返回值: |
null |
注意: |
|
|
默认s1>=s2,程序未处理负数情况 |
|
需要 string.h |
源程序: |
|
|
void sub(char s1[],char s2[],char t[]) |
6.任意进制转换
语法:conversion(char s1[],char s2[],long d1,long d2); |
|
参数: |
|
s[]: |
原进制数字,用字符串表示 |
s2[]: |
转换结果,用字符串表示 |
d1: |
原进制数 |
d2: |
需要转换到的进制数 |
返回值: |
null |
注意: |
|
|
高于9的位数用大写'A'~'Z'表示,2~16位进制通过验证 |
源程序: |
|
|
void conversion(char s[],char s2[],long d1,long d2) |
7.最大公约数、最小公倍数
语法:resulet=hcf(int a,int b)、result=lcd(int a,int b) |
|
参数: |
|
a: |
int a,求最大公约数或最小公倍数 |
b: |
int b,求最大公约数或最小公倍数 |
返回值: |
返回最大公约数(hcf)或最小公倍数(lcd) |
注意: |
|
|
lcd 需要连同 hcf 使用 |
源程序: |
|
|
int hcf(int a,int b) lcd(int u,int v,int h) |
8.组合序列
语法:m_of_n(int m, int n1, int m1, int* a, int head) |
|
参数: |
|
m: |
组合数C的上参数 |
n1: |
组合数C的下参数 |
m1: |
组合数C的上参数,递归之用 |
*a: |
1~n的整数序列数组 |
head: |
头指针 |
返回值: |
null |
注意: |
|
|
*a需要自行产生 |
|
初始调用时,m=m1、head=0 |
|
调用例子:求C(m,n)序列:m_of_n(m,n,m,a,0); |
源程序: |
|
|
void m_of_n(int m, int n1, int m1, int* a, int head) if(m1==n1) |
9.快速傅立叶变换(FFT)
语法:kkfft(double pr[],double pi[],int n,int k,double fr[],double fi[],int l,int il); |
|
参数: |
|
pr[n]: |
输入的实部 |
pi[n]: |
数入的虚部 |
n,k: |
满足n=2^k |
fr[n]: |
输出的实部 |
fi[n]: |
输出的虚部 |
l: |
逻辑开关,0 FFT,1 ifFT |
il: |
逻辑开关,0 输出按实部/虚部;1 输出按模/幅角 |
返回值: |
null |
注意: |
|
|
需要 math.h |
源程序: |
|
|
void kkfft(pr,pi,n,k,fr,fi,l,il) |
10.Ronberg算法计算积分
语法:result=integral(double a,double b); |
|
参数: |
|
a: |
积分上限 |
b: |
积分下限 |
function f: |
积分函数 |
返回值: |
f在(a,b)之间的积分值 |
注意: |
|
|
function f(x)需要自行修改,程序中用的是sina(x)/x |
|
需要 math.h |
|
默认精度要求是1e-5 |
源程序: |
|
|
double f(double x) |
11.行列式计算
语法:result=js(int s[][],int n) |
|
参数: |
|
s[][]: |
行列式存储数组 |
n: |
行列式维数,递归用 |
返回值: |
行列式值 |
注意: |
|
|
函数中常数N为行列式维度,需自行定义 |
源程序: |
|
|
int js(s,n) |
12.求排列组合数
语法:result=P(long n,long m); / result=long C(long n,long m); |
|
参数: |
|
m: |
排列组合的上系数 |
n: |
排列组合的下系数 |
返回值: |
排列组合数 |
注意: |
|
|
符合数学规则:m<=n |
源程序: |
|
|
long P(long n,long m) long C(long n,long m) |
二、字符串处理
1.字符串替换
语法:replace(char str[],char key[],char swap[]); |
|
参数: |
|
str[]: |
在此源字符串进行替换操作 |
key[]: |
被替换的字符串,不能为空串 |
swap[]: |
替换的字符串,可以为空串,为空串表示在源字符中删除key[] |
返回值: |
null |
注意: |
|
|
默认str[]长度小于1000,如否,重新设定设定tmp大小 |
|
需要 string.h |
源程序: |
|
|
void replace(char str[],char key[],char swap[]) |
2.字符串查找
语法:result=strfind(char str[],char key[]); |
|
参数: |
|
str[]: |
在此源字符串进行查找操作 |
key[]: |
被查找的字符串,不能为空串 |
返回值: |
如果查找成功,返回key在str中第一次出现的位置,否则返回-1 |
注意: |
|
|
需要 string.h |
源程序: |
|
|
int strfind(char str[],char key[]) |
3.字符串截取
语法:mid(char str[],int start,int len,char strback[]) |
|
参数: |
|
str[]: |
操作的目标字符串 |
start: |
从第start个字符串开始,截取长度为len的字符 |
len: |
从第start个字符串开始,截取长度为len的字符 |
strback[]: |
截取的到的字符 |
返回值: |
0:超出字符串长度,截取失败;1:截取成功 |
注意: |
|
|
需要 string.h |
源程序: |
|
|
int mid(char str[],int start,int len,char strback[]) |
三、计算几何
1.叉乘法求任意多边形面积
语法:result=polygonarea(Point *polygon,int N); |
|
参数: |
|
*polygon: |
多变形顶点数组 |
N: |
多边形顶点数目 |
返回值: |
多边形面积 |
注意: |
|
|
支持任意多边形,凹、凸皆可 |
|
多边形顶点输入时按顺时针顺序排列 |
源程序: |
|
|
typedef struct { double polygonarea(Point *polygon,int N) for (i=0;i<N;i++) { area /= 2; |
2.求三角形面积
语法:result=area3(float x1,float y1,float x2,float y2,float x3,float y3); |
|
参数: |
|
x1~3: |
三角形3个顶点x坐标 |
y1~3: |
三角形3个顶点y坐标 |
返回值: |
三角形面积 |
注意: |
|
|
需要 math.h |
源程序: |
|
|
float area3(float x1,float y1,float x2,float y2,float x3,float y3) |
3.两矢量间角度
语法:result=angle(double x1, double y1, double x2, double y2); |
|
参数: |
|
x/y1~2: |
两矢量的坐标 |
返回值: |
两的角度矢量 |
注意: |
|
|
返回角度为弧度制,并且以逆时针方向为正方向 |
|
需要 math.h |
源程序: |
|
|
#define PI 3.1415926 |
4.两点距离(2D、3D)
语法:result=distance_2d(float x1,float x2,float y1,float y2); |
|
参数: |
|
x/y/z1~2: |
各点的x、y、z坐标 |
返回值: |
两点之间的距离 |
注意: |
|
|
需要 math.h |
源程序: |
|
|
float distance_2d(float x1,float x2,float y1,float y2) |
5.射向法判断点是否在多边形内部
语法:result=insidepolygon(Point *polygon,int N,Point p); |
|
参数: |
|
*polygon: |
多边形顶点数组 |
N: |
多边形顶点个数 |
p: |
被判断点 |
返回值: |
0:点在多边形内部;1:点在多边形外部 |
注意: |
|
|
若p点在多边形顶点或者边上,返回值不确定,需另行判断 |
|
需要 math.h |
源程序: |
|
|
#define MIN(x,y) (x < y ? x : y) typedef struct { int insidepolygon(Point *polygon,int N,Point p) p1 = polygon[0]; if (counter % 2 == 0) |
6.判断点是否在线段上
语法:result=Pointonline(Point p1,Point p2,Point p); |
|
参数: |
|
p1、p2: |
线段的两个端点 |
p: |
被判断点 |
返回值: |
0:点在不在线段上;1:点在线段上 |
注意: |
|
|
若p线段端点上返回1 |
|
需要 math.h |
源程序: |
|
|
#define MIN(x,y) (x < y ? x : y) typedef struct { int FC(double x1,double x2) |
7.判断两线段是否相交
语法:result=sectintersect(Point p1,Point p2,Point p3,Point p4); |
|
参数: |
|
p1~4: |
两条线段的四个端点 |
返回值: |
0:两线段不相交;1:两线段相交;2两线段首尾相接 |
注意: |
|
|
p1!=p2;p3!=p4; |
源程序: |
|
|
#define MIN(x,y) (x < y ? x : y) typedef struct { int lineintersect(Point p1,Point p2,Point p3,Point p4) //跨立试验 |
8.判断线段与直线是否相交
语法:result=lineintersect(Point p1,Point p2,Point p3,Point p4); |
|
参数: |
|
p1、p2: |
线段的两个端点 |
p3、p4: |
直线上的两个点 |
返回值: |
0:线段直线不相交;1:线段和直线相交 |
注意: |
|
|
如线段在直线上,返回 1 |
源程序: |
|
|
typedef struct { int lineintersect(Point p1,Point p2,Point p3,Point p4) |
9.点到线段最短距离
语法:result=mindistance(Point p1,Point p2,Point q); |
|
参数: |
|
p1、p2: |
线段的两个端点 |
q: |
判断点 |
返回值: |
点q到线段p1p2的距离 |
注意: |
|
|
需要 math.h |
源程序: |
|
|
#define MIN(x,y) (x < y ? x : y) typedef struct { double mindistance(Point p1,Point p2,Point q) |
10.求两直线的交点
语法:result=mindistance(Point p1,Point p2,Point q); |
|
参数: |
|
p1~p4: |
直线上不相同的两点 |
*p: |
通过指针返回结果 |
返回值: |
1:两直线相交;2:两直线平行 |
注意: |
|
|
如需要判断两线段交点,检验k和对应k1(注释中)的值是否在0~1之间,用在0~1之间的那个求交点 |
源程序: |
|
|
typedef struct { int linecorss(Point p1,Point p2,Point p3,Point p4,Point *p) //同一直线 if ((p4.x-p3.x)*(p1.y-p3.y)-(p4.y-p3.y)*(p1.x-p3.x)==0&& (p2.x-p1.x)*(p1.y-p3.y)-(p2.y-p1.y)*(p1.x-p3.x)==0) return 2; //平行,不同一直线 if ((p4.y-p3.y)*(p2.x-p1.x)-(p4.x-p3.x)*(p2.y-p1.y)==0) return 0;
k=((p4.x-p3.x)*(p1.y-p3.y)-(p4.y-p3.y)*(p1.x-p3.x))/((p4.y-p3.y)*(p2.x-p1.x)-(p4.x-p3.x)*(p2.y-p1.y)); //k1=((p2.x-p1.x)*(p1.y-p3.y)-(p2.y-p1.y)*(p1.x-p3.x))/((p4.y-p3.y)*(p2.x-p1.x)-(p4.x-p3.x)*(p2.y-p1.y)); (*p).x=p1.x+k*(p2.x-p1.x); (*p).y=p1.y+k*(p2.y-p1.y); return 1;//有交点} |
11.判断一个封闭图形是凹集还是凸集
语法:result=convex(Point *p,int n); |
|
参数: |
|
*p: |
封闭曲线顶点数组 |
n: |
封闭曲线顶点个数 |
返回值: |
1:凸集;-1:凹集;0:曲线不符合要求无法计算 |
注意: |
|
|
默认曲线为简单曲线:无交叉、无圈 |
源程序: |
|
|
typedef struct { int convex(Point *p,int n) if (n < 3) for (i=0;i<n;i++) { |
12.Graham扫描法寻找凸包
语法:Graham_scan(Point PointSet[],Point ch[],int n,int &len); |
|
参数: |
|
PointSet[]: |
输入的点集 |
ch[]: |
输出的凸包上的点集,按照逆时针方向排列 |
n: |
PointSet中的点的数目 |
len: |
输出的凸包上的点的个数 |
返回值: |
null |
源程序: |
|
|
struct Point{ float multiply(Point p1,Point p2,Point p0) float distance(Point p1,Point p2) void Graham_scan(Point PointSet[],Point ch[],int n,int &len) |
四、数论
1.x的二进制长度
语法:result=BitLength(int x); |
|
参数: |
|
x: |
测长的x |
返回值: |
x的二进制长度 |
源程序: |
|
|
int BitLength(int x) |
2.返回x的二进制表示中从低到高的第i位
语法:result=BitAt(int x, int i); |
|
参数: |
|
x: |
十进制 x |
i: |
要求二进制的第i位 |
返回值: |
返回x的二进制表示中从低到高的第i位 |
注意: |
|
|
最低位为第一位 |
源程序: |
|
|
int BitAt(int x, int i) |
3.模取幂运算
语法:result=Modular_Expoent(int a,int b,int n); |
|
参数: |
|
a、b、n: |
a^b mod n 的对应参数 |
返回值: |
a^b mod n 的值 |
注意: |
|
|
需要BitLength和BitAt |
源程序: |
|
|
int Modular_Expoent(int a,int b,int n) |
4.求解模线性方程
语法:result=modular_equation(int a,int b,int n); |
|
参数: |
|
a、b、n: |
ax=b (mod n) 的对应参数 |
返回值: |
方程的解 |
源程序: |
|
|
int ext_euclid(int a,int b,int &x,int &y) //求gcd(a,b)=ax+by |
5.求解模线性方程组(中国余数定理)
语法:result=Modular_Expoent(int a,int b,int n); |
|
参数: |
|
B[]、W[]: |
a=B[] (mod W[]) 的对应参数 |
返回值: |
a 的值 |
注意: |
|
|
其中W[],B[]已知,W[i]>0且W[i]与W[j]互质, 求a |
源程序: |
|
|
int ext_euclid(int a,int b,int &x,int &y) //求gcd(a,b)=ax+by |
6.筛法素数产生器
语法:result=prime(int a[],int n); |
|
参数: |
|
a[]: |
用于返回素数的数组 |
n: |
产生n以内的素数,按升序放入a[]中 |
返回值: |
n以内素数的个数 |
注意: |
|
|
其中W[],B[]已知,W[i]>0且W[i]与W[j]互质, 求a |
源程序: |
|
|
int prime(int a[],int n) |
7.判断一个数是否素数
语法:result=comp(int n); |
|
参数: |
|
n: |
判断n是否素数 |
返回值: |
素数返回1,否则返回0 |
源程序: |
|
|
int comp(int n) |
五、图论
1.Prim算法求最小生成树
语法:prim(Graph G,int vcount,int father[]); |
|
参数: |
|
G: |
图,用邻接矩阵表示 |
vcount: |
表示图的顶点个数 |
father[]: |
用来记录每个节点的父节点 |
返回值: |
null |
注意: |
|
|
常数max_vertexes为图最大节点数 |
|
常数infinity为无穷大 |
源程序: |
|
|
#define infinity 1000000 |
2.Dijkstra算法求单源最短路径
语法:result=Dijkstra(Graph G,int n,int s,int t, int path[]); |
|
参数: |
|
G: |
图,用邻接矩阵表示 |
n: |
图的顶点个数 |
s: |
开始节点 |
t: |
目标节点 |
path[]: |
用于返回由开始节点到目标节点的路径 |
返回值: |
最短路径长度 |
注意: |
|
|
输入的图的权必须非负 |
|
顶点标号从0开始 |
|
用如下方法打印路径: |
源程序: |
|
|
int Dijkstra(Graph G,int n,int s,int t, int path[]) |
3.Bellman-ford算法求单源最短路径
语法:result=Bellman_ford(Graph G,int n,int s,int t,int path[],int success); |
|
参数: |
|
G: |
图,用邻接矩阵表示 |
n: |
图的顶点个数 |
s: |
开始节点 |
t: |
目标节点 |
path[]: |
用于返回由开始节点到目标节点的路径 |
success: |
函数是否执行成功 |
返回值: |
最短路径长度 |
注意: |
|
|
输入的图的权可以为负,如果存在一个从源点可达的权为负的回路则success=0 |
|
顶点标号从0开始 |
|
用如下方法打印路径: |
源程序: |
|
|
int Bellman_ford(Graph G,int n,int s,int t,int path[],int success) |
4.Floyd-Warshall算法求每对节点间最短路径
语法:Floyd_Washall(Graph G,int n,Graph D,Graph P); |
|
参数: |
|
G: |
图,用邻接矩阵表示 |
n: |
图的顶点个数 |
D: |
D[i,j]表示从i到j的最短距离 |
P: |
P[i,j]表示从i到j的最短路径上j 的父节点 |
返回值: |
null |
源程序: |
|
|
void Floyd_Washall(Graph G,int n,Graph D,Graph P) |
六、排序/查找
1.快速排序
语法:quicksort(int l,int r,int b[]); |
|
参数: |
|
l: |
排序上界,开始时l=0 |
r: |
排序下界,开始时r=数组元素个数 |
b[]: |
被排序的元素 |
返回值: |
null |
注意: |
|
|
输出升序序列 |
源程序: |
|
|
void quicksort(int l,int r,int b[]) |
2.希尔排序
语法:shellsort(int a[],int n); |
|
参数: |
|
n: |
数组元素个数 |
a[]: |
待排序数组 |
返回值: |
null |
注意: |
|
|
输出升序序列 |
源程序: |
|
|
void shellsort(int a[],int n) |
3.选择法排序
语法:sort(int t[],int n); |
|
参数: |
|
t[]: |
待排序数组 |
n: |
数组t[]元素的个数 |
返回值: |
null |
注意: |
|
|
输出升序序列 |
|
小规模排序用 |
源程序: |
|
|
void sort(int t[],int n) |
4.二分查找
语法:result=search_bin(int *t,int k); |
|
参数: |
|
t[]: |
待查找数组 |
k: |
查找关键字 |
返回值: |
如果k在t[]中存在,输出i:t[i]=k,否则输出-1 |
注意: |
|
|
要求查找数组是有序升序序列 |
源程序: |
|
|
int search_bin(int *t,int k) |
七、数据结构
1.顺序队列
源程序: |
|
|
#define maxsize 100 int sqinit(sqqueue *p) //队列初始化 int enqueue(sqqueue *q, int e) //入队 int dequeue(sqqueue *q) //出队 int empty(sqqueue *q) //判空 int gethead(sqqueue *q) //取得头元素 void display(sqqueue *q) //显示所有元素 main(sqqueue *head) //函数使用样例 |
2.顺序栈
源程序: |
|
|
#define m 100 init(stackstru *s) /*装入栈*/ int push(stackstru *s,int x) /*入栈操作*/ void display(stackstru *s) /*显示栈所有数据*/ int pop(stackstru *s) /*出栈操作并返回被删除的那个记录*/ main(stackstru *p) //函数使用演示 |
3.链表
源程序: |
|
|
# define null 0 main()
int length (struct LNode **p) ElemType get(struct LNode **p,int i) int locate(struct LNode **p,ElemType x) void insert(struct LNode **p,ElemType x,int i) int delete(struct LNode **p,int i) void display(struct LNode **p) |
4.链栈
源程序: |
|
|
# define null 0 int pushlink(stackk *s,int x) int gettop(stackk *s) |
5.二叉树
源程序: |
|
|
typedef struct bitnode void createbitree(t,n) void countleaf(t,c) int treehigh(t) |
标签:p2,常用,p1,return,Point,int,代码,ACM,printf 来源: https://www.cnblogs.com/wangprince2017/p/16230308.html