ACM模板
acm 算法模板 适合初学者使用
三角形面积计算 (1)字典树模板 (2)求线段所在直线 (5)求外接圆 (5)求内接圆 (6)判断点是否在直线上 (8)简单多边形面积计算公式 (8)stein算法求最大共约数 (9)最长递增子序列模板——o(nlogn算法实现) (9)判断图中同一直线的点的最大数量 (10)公因数和公倍数 (12)已知先序中序求后序 (12)深度优先搜索模板 (13)匈牙利算法——二部图匹配BFS实现 (15)带输出路径的prime算法 (17)prime模板 (18)kruskal模板 (19)dijsktra (22)并查集模板 (23)高精度模板 (24)三角形面积计算//已知三条边和外接圆半径,公式为s = a*b*c/(4*R)double GetArea(double a, double b, double c, double R){return a*b*c/4/R;}//已知三条边和内接圆半径,公式为s = prdouble GetArea(double a, double b, double c, double r){return r*(a+b+c)/2;}//已知三角形三条边,求面积double GetArea(doule a, double b, double c){double p = (a+b+c)/2;return sqrt(p*(p-a)*(p-b)*(p-c));}//已知道三角形三个顶点的坐标struct Point{double x, y;Point(double a = 0, double b = 0){x = a; y = b;}};double GetArea(Point p1, Point p2, Point p3){double t =-p2.x*p1.y+p3.x*p1.y+p1.x*p2.y-p3.x*p2.y-p1.x*p3.y+p2.x*p3.y;if(t < 0) t = -t;return t/2;}字典树模板#include <stdio.h>#include <string.h>#include <memory.h>#define BASE_LETTER 'a'#define MAX_TREE 35000#define MAX_BRANCH 26struct{int next[MAX_BRANCH]; //记录分支的位置int c[MAX_BRANCH]; //查看分支的个数int flag; //是否存在以该结点为终止结点的东东,可以更改为任意的属性}trie[MAX_TREE];int now;void init(){now = 0;memset(&trie[now], 0, sizeof(trie[now]));now ++;}int add (){memset(&trie[now], 0, sizeof(trie[now]));return now++;}int insert( char *str){int pre = 0, addr;while( *str != 0 ){addr = *str - BASE_LETTER;if( !trie[pre].next[addr] )trie[pre].next[addr] = add();trie[pre].c[addr]++;pre = trie[pre].next[addr];str ++;}trie[pre].flag = 1;return pre;}int search( char *str ){int pre = 0, addr;while( *str != 0 ){addr = *str - BASE_LETTER;if ( !trie[pre].next[addr] )return 0;pre = trie[pre].next[addr];str ++;}if( !trie[pre].flag )return 0;return pre;}pku2001题,源代码:void check( char *str ){int pre = 0, addr;while(*str != 0){addr = *str - BASE_LETTER;if( trie[pre].c[addr] == 1) {printf("%c\n", *str);return;}printf("%c", *str);pre = trie[pre].next[addr];str ++;}printf("\n");}char input[1001][25];int main(){int i = 0,j;init();while(scanf("%s", input[i]) != EOF){getchar();insert(input[i]);i++;}for(j = 0; j < i; j ++){printf("%s ", input[j]);check(input[j]);}return 0;}求线段所在直线//*****************************线段所在的直线struct Line{double a, b, c;};struct Point{double x, y;}Line GetLine(Point p1, Point p2){//ax+by+c = 0返回直线的参数Line line;line.a = p2.y - p1.y;line.b = p1.x - p2.x;line.c = p2.x*p1.y - p1.x*p2.y;return line;}求外接圆//***************已知三角形三个顶点坐标,求外接圆的半径和坐标********************struct Point{double x, y;Point(double a = 0, double b = 0){x = a; y = b;}};struct TCircle{double r;Point p;}double distance(Point p1, Point p2){return sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));}double GetArea(doule a, double b, double c){double p = (a+b+c)/2;return sqrt(p*(p-a)*(p-b)*(p-c));}TCircle GetTCircle(Point p1, Point p2, Point p3){double a, b, c;double xa,ya, xb, yb, xc, yc, c1, c2;TCircle tc;a = distance(p1, p2);b = distance(p2, p3);c = distance(p3, p1);//求半径tc.r = a*b*c/4/GetArea(a, b, c);//求坐标xa = p1.x; ya = p1.b;xb = p2.x; yb = p2.b;xc = p3.x; yc = p3.b;c1 = (xa*xa + ya*ya - xb*xb - yb*yb)/2;c2 = (xa*xa + ya*ya - xc*xc - yc*yc)/2;tc.p.x = (c1*(ya-yc) - c2*(ya-yb))/((xa-xb)*(ya-yc) - (xa-xc)*(ya-yb)); tc.p.y = (c1*(xa-xc) - c2*(xa-xb))/((ya-yb)*(xa-xc) - (ya-yc)*(xa-xb));return tc;}求内接圆struct Point{double x, y;Point(double a = 0, double b = 0){x = a; y = b;}};struct TCircle{double r;Point p;}double distance(Point p1, Point p2){return sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));}double GetArea(doule a, double b, double c){double p = (a+b+c)/2;return sqrt(p*(p-a)*(p-b)*(p-c));}TCircle GetTCircle(Point p1, Point p2, Point p3){double a, b, c;double xa,ya, xb, yb, xc, yc, c1, c2, f1, f2;double A,B,C;TCircle tc;a = distance(p1, p2);b = distance(p3, p2);c = distance(p3, p1);//求半径tc.r = 2*GetArea(a, b, c)/(a+b+c);//求坐标A = acos((b*b+c*c-a*a)/(2*b*c));B = acos((a*a+c*c-b*b)/(2*a*c));C = acos((a*a+b*b-c*c)/(2*a*b));p = sin(A/2); p2 = sin(B/2); p3 = sin(C/2);xb = p1.x; yb = p1.b;xc = p2.x; yc = p2.b;xa = p3.x; ya = p3.b;f1 = ( (tc.r/p2)*(tc.r/p2) - (tc.r/p)*(tc.r/p) + xa*xa - xb*xb + ya*ya - yb*yb)/2;f2 = ( (tc.r/p3)*(tc.r/p3) - (tc.r/p)*(tc.r/p) + xa*xa - xc*xc + ya*ya - yc*yc)/2;tc.p.x = (f1*(ya-yc) - f2*(ya-yb))/((xa-xb)*(ya-yc)-(xa-xc)*(ya-yb)); tc.p.y = (f1*(xa-xc) - f2*(xa-xb))/((ya-yb)*(xa-xc)-(ya-yc)*(xa-xb));return tc;}判断点是否在直线上//**************判断点是否在直线上********************* //判断点p是否在直线[p1,p2]struct Point{double x,y;};bool isPointOnSegment(Point p1, Point p2, Point p0){//叉积是否为0,判断是否在同一直线上if((p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y) != 0)return false;//判断是否在线段上if((p0.x > p1.x && p0.x > p2.x) || (p0.x < p1.x && p0.x < p2.x)) return false;if((p0.y > p1.y && p0.y > p1.y) || (p0.y < p1.y && p0.y < p2.y)) return false;return true;}简单多边形面积计算公式struct Point{double x, y;Point(double a = 0, double b = 0){x = a; y = b;}};Point pp[10];double GetArea(Point *pp, int n){//n为点的个数,pp中记录的是点的坐标int i = 1;double t = 0;for(; i <= n-1; i++)t += pp[i-1].x*pp[i].y - pp[i].x*pp[i-1].y;t += pp[n-1].x*pp[0].y - pp[0].x*pp[n-1].y;if(t < 0) t = -t;return t/2;}stein算法求最大共约数int gcd(int a,int b){if (a == 0) return b;if (b == 0) return a;if (a % 2 == 0 && b % 2 == 0) return 2 * gcd(a/2,b/2); else if (a % 2 == 0) return gcd(a/2,b);else if (b % 2 == 0) return gcd(a,b/2);else return gcd(abs(a-b),min(a,b));}最长递增子序列模板——o(nlogn算法实现)#include <stdio.h>#define MAX 40000int array[MAX], B[MAX];int main(){int count,i,n,left,mid,right,Blen=0,num;scanf("%d",&count); //case的个数while(count--){scanf("%d",&n); //每组成员的数量Blen = 0;for(i=1;i<=n;i++)scanf("%d",&array[i]); //读入每个成员for(i=1;i<=n;i++){num = array[i];left = 1;right = Blen;while(left<=right){mid = (left+right)/2;if(B[mid]<num)left = mid+1;elseright = mid-1;}B[left] = num;if(Blen<left)Blen++;}printf("%d\n",Blen);//输出结果}return 1;}判断图中同一直线的点的最大数量#include <iostream>#include <cstdio>#include <memory>using namespace std;#define MAX 1010 //最大点的个数struct point{int x,y;}num[MAX];int used[MAX][MAX*2]; //条件中点的左边不会大于1000,just equal MAX int countN[MAX][MAX*2];#define abs(a) (a>0?a:(-a))int GCD(int x, int y){int temp;if(x < y){temp = x; x = y; y = temp;}while(y != 0){temp = y;y = x % y;x = temp;}return x;}int main(){int n,i,j;int a,b,d,ans;while(scanf("%d", &n)==1){//initeans = 1;memset(used, 0, sizeof(used));memset(countN, 0, sizeof(countN));//readfor(i = 0; i < n; i++)scanf("%d%d", &num[i].x, &num[i].y);for(i = 0; i < n-1; i++){for(j = i+1; j < n; j++){b = num[j].y-num[i].y;a = num[j].x-num[i].x;if(a < 0) //这样可以让(2,3)(-2,-3)等价{a = -a; b = -b;}d = GCD(a,abs(b));a /= d;b /= d; b += 1000;//条件中点的左边不会大于1000if(used[a][b] != i+1){used[a][b] = i+1;countN[a][b] = 1;}else{countN[a][b]++;if(ans < countN[a][b])ans = countN[a][b];}}//for}//forprintf("%d\n", ans+1);}return 0;}公因数和公倍数int GCD(int x, int y){int temp;if(x < y){temp = x; x = y; y = temp;}while(y != 0){temp = y;y = x % y;x = temp;}return x;}int beishu(int x, int y){return x * y / GCD(x,y);}已知先序中序求后序#include <iostream>#include <string>using namespace std;string post;void fun(string pre, string mid){if(pre == "" || mid == "") return;int i = mid.find(pre[0]);fun(pre.substr(1,i), mid.substr(0,i));fun(pre.substr(i+1, (int)pre.length()-i-1), mid.substr(i+1, (int)mid.length()-i-1));post += pre[0];}int main(){string pre, mid;while(cin >> pre){cin >> mid;post.erase();fun(pre, mid);cout << post << endl;}return 0;}深度优先搜索模板int t; //t用来标识要搜索的元素int count; //count用来标识搜索元素的个数int data[m][n]; //data用来存储数据的数组//注意,数组默认是按照1……n存储,即没有第0行//下面是4个方向的搜索,void search(int x, int y){data[x][y] = *; //搜索过进行标记if(x-1 >= 1 && data[x-1][y] == t){count++;search(x-1,y);}if(x+1 <= n && data[x+1][y] == t){count++;search(x+1,y);}if(y-1 >= 1 && data[x][y-1] == t){count++;search(x,y-1);}if(y+1 <= n && data[x][y+1] == t){count++;search(x,y+1);}}//下面是8个方向的搜索void search(int x, int y){data[x][y] = *; //搜索过进行标记if(x-1 >= 1){if(data[x-1][y] == t){count++;search(x-1,y);}if(y-1 >= 1 && data[x-1][y-1] == t) {count++;search(x-1,y-1);}if(y+1 <= n && data[x-1][y+1] == t) {count++;search(x-1,y+1);}}if(x+1 <= n){if(data[x+1][y] == t){count++;search(x+1,y);}if(y-1 >= 1 && data[x+1][y-1] == t) {count++;search(x+1,y-1);}if(y+1 <= n && data[x+1][y+1] == t) {count++;search(x+1,y+1);}}if(y-1 >= 1 && data[x][y-1] == t){count++;search(x,y-1);}if(y+1 <= n && data[x][y+1] == t){count++;search(x,y+1);}}匈牙利算法——二部图匹配BFS实现//匈牙利算法实现#define MAX 310 //二部图一侧顶点的最大个数int n,m; //二分图的两个集合分别含有n和m个元素。
我的ACM算法模板
ACM模板[王克纯2020年9月21日最大子串int maxSum(int * a,int n){int sum = a[0],b = 0;for(int i=0;i<n;++i){if(b>0) b += a[i];else b = a[i];if(b > sum) sum = b;}return sum;}int Kadane(const int array[], size_t length, unsigned int& left, unsigned int& right){unsigned int i, cur_left, cur_right;int cur_max, max;cur_max = max = left = right = cur_left = cur_right = 0;for(i = 0; i < length; ++i){cur_max += array[i];if(cur_max > 0){cur_right = i;if(max < cur_max){max = cur_max;left = cur_left;right = cur_right;}}else{cur_max = 0;cur_left = cur_right = i + 1;}}return max;} 快速幂void js(int &a,int &b,int num) {b=1;while(num){if(num&1) b*=a;num>>=1;a*=a;}}矩阵乘法struct mat{int n,m;//n行m列int data[MAX][MAX];};void mul(const mat& a,const mat& b,mat& c) //c=a*b{int i,j,k;if (a.m!=b.n); //报错c.n=a.n,c.m=b.m;for (i=0;i<c.n;i++){for (j=0;j<c.m;j++){for (c.data[i][j]=k=0;k<a.m;k++) {c.data[i][j]+=a.data[i][k]*b.dat a[k][j]%m;//m为余数}c.data[i][j]%=m;}}}Bit位操作(宏定义,内联函数,stl)} #define bitwrite(a,i,n)(n)?(a)[(i)/8]|=1<<(i)%8:(a)[(i)/8]&=~(1<<(i)%8)//数组a的第i位写入n;#define bitread(a,i)((a)[(i)/8]>>((i)%8))&1//读取数组a的第i位inline void write(int i,int n){n?a[i/8]|=1<<i%8:a[i/8]&=~(1<<i% 8);}inline int read(int i){return (a[i/8]>>(i%8))&1;}#include<bitset>bitset<MAX> b;错排公式为M(n)=n!(1/2!-1/3!+…..+(-1)^n/n!)M(n)=n!-n!/1!+n!/2!-n!/3!+…+(-1)^n*n!/n!=sigma(k=2~n) (-1)^k*n!/k!Dn=[n!/e+0.5]容斥原理M(n)=n![1/0!-1/1!+1/2!-1/3!+1/4! +..+(-1)^n/n!]二分模板LL findr(LL array, LL low, LL high,LL target){while(low <= high){LL mid = (low + high)/2;if (array[mid] > target) high = mid - 1;else if (array[mid] < target) low = mid + 1;else return mid;}return -1;复用代码#include<stdio.h>#include<stdlib.h>#include<string.h>#define MAX 10void print(mat t){printf("*****************\n") ;for(int i=0;i<t.n;i++){for(int j=0;j<t.m;j++){printf("%d",t.data[i][j]);}putchar('\n');}}一些常量和函数:最大Long long __int64 INF = ~(((__int64)0x1)<<63);ceil()向上取整(math.h)floor()向下取整c字符串处理函数1)提取子串--strstr函数原型:char* strstr(char*src,char*find)函数说明:从字符串src中寻找find第一次出现的位置(不比较结束符NULL)返回值:返回指向第一次出现find位置的指针,如果没有找到则返回NULL2)接尾连接--strcat函数原型:char* strcat(char*dest,char*src)函数说明:把src所指字符串添加到dest结尾处(覆盖dest结尾处的'\0')并添加'\0'3)部分连接--strncat函数原型:char* strncat(char*dest,char*src,int n);函数说明:把src所指字符串的前n个字符添加到dest结尾处(覆盖dest结尾处的’\0’)并添加’’\0’.返回值:返回指向dest的指针。
ACM程序竞赛计算几何超全模板
/*计算几何目录㈠点的基本运算1. 平面上两点之间距离12. 判断两点是否重合13. 矢量叉乘14. 矢量点乘25. 判断点是否在线段上26. 求一点饶某点旋转后的坐标27. 求矢量夹角2㈡线段及直线的基本运算1. 点与线段的关系32. 求点到线段所在直线垂线的垂足43. 点到线段的最近点44. 点到线段所在直线的距离45. 点到折线集的最近距离46. 判断圆是否在多边形内57. 求矢量夹角余弦58. 求线段之间的夹角59. 判断线段是否相交610.判断线段是否相交但不交在端点处611.求线段所在直线的方程612.求直线的斜率713.求直线的倾斜角714.求点关于某直线的对称点715.判断两条直线是否相交及求直线交点716.判断线段是否相交,如果相交返回交点7㈢多边形常用算法模块1. 判断多边形是否简单多边形82. 检查多边形顶点的凸凹性93. 判断多边形是否凸多边形94. 求多边形面积95. 判断多边形顶点的排列方向,方法一106. 判断多边形顶点的排列方向,方法二107. 射线法判断点是否在多边形内108. 判断点是否在凸多边形内119. 寻找点集的graham算法1210.寻找点集凸包的卷包裹法1311.判断线段是否在多边形内1412.求简单多边形的重心1513.求凸多边形的重心1714.求肯定在给定多边形内的一个点1715.求从多边形外一点出发到该多边形的切线1816.判断多边形的核是否存在19㈣圆的基本运算1 .点是否在圆内202 .求不共线的三点所确定的圆21㈤矩形的基本运算1.已知矩形三点坐标,求第4点坐标22㈥常用算法的描述22㈦补充1.两圆关系:242.判断圆是否在矩形内:243.点到平面的距离:254.点是否在直线同侧:255.镜面反射线:256.矩形包含:267.两圆交点:278.两圆公共面积:289. 圆和直线关系:2910. 内切圆:3011. 求切点:3112. 线段的左右旋:3113.公式:32*//* 需要包含的头文件*/#include <cmath >/* 常用的常量定义*/const double INF = 1E200const double EP = 1E-10const int MAXV = 300const double PI = 3.14159265/* 基本几何结构*/struct POINT{double x;double y;POINT(double a=0, double b=0) { x=a; y=b;} //constructor};struct LINESEG{POINT s;POINT e;LINESEG(POINT a, POINT b) { s=a; e=b;}LINESEG() { }};struct LINE // 直线的解析方程a*x+b*y+c=0 为统一表示,约定a >= 0{double a;double b;double c;LINE(double d1=1, double d2=-1, double d3=0) {a=d1; b=d2; c=d3;}};/*********************** ** 点的基本运算** ***********************/double dist(POINT p1,POINT p2) // 返回两点之间欧氏距离{return( sqrt( (p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y) ) );}bool equal_point(POINT p1,POINT p2) // 判断两个点是否重合{return ( (abs(p1.x-p2.x)<EP)&&(abs(p1.y-p2.y)<EP) );}/****************************************************************************** r=multiply(sp,ep,op),得到(sp-op)和(ep-op)的叉积r>0:ep在矢量opsp的逆时针方向;r=0:opspep三点共线;r<0:ep在矢量opsp的顺时针方向******************************************************************************* /double multiply(POINT sp,POINT ep,POINT op){return((sp.x-op.x)*(ep.y-op.y)-(ep.x-op.x)*(sp.y-op.y));}/*r=dotmultiply(p1,p2,op),得到矢量(p1-op)和(p2-op)的点积,如果两个矢量都非零矢量r<0:两矢量夹角为锐角;r=0:两矢量夹角为直角;r>0:两矢量夹角为钝角******************************************************************************* /double dotmultiply(POINT p1,POINT p2,POINT p0){return ((p1.x-p0.x)*(p2.x-p0.x)+(p1.y-p0.y)*(p2.y-p0.y));}/****************************************************************************** 判断点p是否在线段l上条件:(p在线段l所在的直线上) && (点p在以线段l为对角线的矩形内)******************************************************************************* /bool online(LINESEG l,POINT p){return( (multiply(l.e,p,l.s)==0) &&( ( (p.x-l.s.x)*(p.x-l.e.x)<=0 )&&( (p.y-l.s.y)*(p.y-l.e.y)<=0 ) ) ); }// 返回点p以点o为圆心逆时针旋转alpha(单位:弧度)后所在的位置POINT rotate(POINT o,double alpha,POINT p){POINT tp;p.x-=o.x;p.y-=o.y;tp.x=p.x*cos(alpha)-p.y*sin(alpha)+o.x;tp.y=p.y*cos(alpha)+p.x*sin(alpha)+o.y;return tp;}/* 返回顶角在o点,起始边为os,终止边为oe的夹角(单位:弧度)角度小于pi,返回正值角度大于pi,返回负值可以用于求线段之间的夹角原理:r = dotmultiply(s,e,o) / (dist(o,s)*dist(o,e))r'= multiply(s,e,o)r >= 1 angle = 0;r <= -1 angle = -PI-1<r<1 && r'>0 angle = arccos(r)-1<r<1 && r'<=0 angle = -arccos(r)*/double angle(POINT o,POINT s,POINT e){double cosfi,fi,norm;double dsx = s.x - o.x;double dsy = s.y - o.y;double dex = e.x - o.x;double dey = e.y - o.y;cosfi=dsx*dex+dsy*dey;norm=(dsx*dsx+dsy*dsy)*(dex*dex+dey*dey);cosfi /= sqrt( norm );if (cosfi >= 1.0 ) return 0;if (cosfi <= -1.0 ) return -3.1415926;fi=acos(cosfi);if (dsx*dey-dsy*dex>0) return fi; // 说明矢量os 在矢量oe的顺时针方向return -fi;}/*****************************\* ** 线段及直线的基本运算** *\*****************************//* 判断点与线段的关系,用途很广泛本函数是根据下面的公式写的,P是点C到线段AB所在直线的垂足AC dot ABr = ---------||AB||^2(Cx-Ax)(Bx-Ax) + (Cy-Ay)(By-Ay)= -------------------------------L^2r has the following meaning:r=0 P = Ar=1 P = Br<0 P is on the backward extension of ABr>1 P is on the forward extension of AB0<r<1 P is interior to AB*/double relation(POINT p,LINESEG l){LINESEG tl;tl.s=l.s;tl.e=p;return dotmultiply(tl.e,l.e,l.s)/(dist(l.s,l.e)*dist(l.s,l.e));}// 求点C到线段AB所在直线的垂足PPOINT perpendicular(POINT p,LINESEG l){double r=relation(p,l);POINT tp;tp.x=l.s.x+r*(l.e.x-l.s.x);tp.y=l.s.y+r*(l.e.y-l.s.y);return tp;}/* 求点p到线段l的最短距离,并返回线段上距该点最近的点np注意:np是线段l上到点p最近的点,不一定是垂足*/double ptolinesegdist(POINT p,LINESEG l,POINT &np){double r=relation(p,l);if(r<0){np=l.s;return dist(p,l.s);}if(r>1){np=l.e;return dist(p,l.e);}np=perpendicular(p,l);return dist(p,np);}// 求点p到线段l所在直线的距离,请注意本函数与上个函数的区别double ptoldist(POINT p,LINESEG l){return abs(multiply(p,l.e,l.s))/dist(l.s,l.e);}/* 计算点到折线集的最近距离,并返回最近点.注意:调用的是ptolineseg()函数*/double ptopointset(int vcount,POINT pointset[],POINT p,POINT &q) {int i;double cd=double(INF),td;LINESEG l;POINT tq,cq;for(i=0;i<vcount-1;i++)l.s=pointset[i];l.e=pointset[i+1];td=ptolinesegdist(p,l,tq);if(td<cd){cd=td;cq=tq;}}q=cq;return cd;}/* 判断圆是否在多边形内.ptolineseg()函数的应用2 */bool CircleInsidePolygon(int vcount,POINT center,double radius,POINT polygon[]){POINT q;double d;q.x=0;q.y=0;d=ptopointset(vcount,polygon,center,q);if(d<radius||fabs(d-radius)<EP)return true;elsereturn false;}/* 返回两个矢量l1和l2的夹角的余弦(-1 --- 1)注意:如果想从余弦求夹角的话,注意反余弦函数的定义域是从0到pi */double cosine(LINESEG l1,LINESEG l2){return (((l1.e.x-l1.s.x)*(l2.e.x-l2.s.x) +(l1.e.y-l1.s.y)*(l2.e.y-l2.s.y))/(dist(l1.e,l1.s)*dist(l2.e,l2.s))) );}// 返回线段l1与l2之间的夹角单位:弧度范围(-pi,pi)double lsangle(LINESEG l1,LINESEG l2){POINT o,s,e;o.x=o.y=0;s.x=l1.e.x-l1.s.x;s.y=l1.e.y-l1.s.y;e.x=l2.e.x-l2.s.x;e.y=l2.e.y-l2.s.y;return angle(o,s,e);// 如果线段u和v相交(包括相交在端点处)时,返回true////判断P1P2跨立Q1Q2的依据是:( P1 - Q1 ) ×( Q2 - Q1 ) * ( Q2 - Q1 ) ×( P2 - Q1 ) >= 0。
acm模板整理和使用方法
acm模板整理和使用方法[acm模板整理和使用方法]ACM模板指的是计算机科学中常用的算法模板,是计算机专业的学生在学习算法和数据结构时必需掌握的内容。
ACM模板整理和使用方法主要包括以下问题:一、为什么要使用ACM模板?ACM模板能使算法实现变得更简单、更方便、更快捷。
尤其在ACM竞赛中,使用优秀的模板可以节省编程时间,避免出现冗余代码,使得编程效率大幅提升。
二、哪些算法需要掌握?许多常见的算法,如快速排序、线段树、并查集、Kruskal算法、Dijkstra算法、最小生成树问题等,都需要掌握。
因此,算法学习和掌握是使用ACM模板的前提。
三、如何整理和使用ACM模板?1.整理ACM模板将常用的算法的代码整理,以函数或者类的形式存放在一个文件中。
注意代码要有良好的注释,易于阅读和理解。
2.旧的代码调试如果有其他ACM竞赛选手或者教练的旧代码,需要先将其调试通过。
因为在ACM比赛中,时间十分宝贵。
如果没有调试好的代码可以使用,建议可以使用OJ网站上的代码进行练习。
3.在比赛中使用和修改模板在ACM比赛中,选手需要快速编写正确的程序并提交到OJ网站。
使用模板可以节省时间和精力,但有时候需要针对具体的问题进行修改。
在修改时需要小心,一定要保证修改后的代码与原始模板的代码所实现的算法是等效的。
4.维护和更新模板ACM模板需要不断地维护和更新,特别是在涉及到新的算法或者数据结构时。
保证ACM模板的有效性和及时性非常重要,这需要持续的学习和探索。
四、如何学习和掌握ACM模板?1.选择学习和观察别人的代码一个好的方式是看国内和国际大佬们的代码,学习他们的代码风格和思考方式。
了解其他人的ACM模板如何实现,可以帮助你提高代码风格和技术水平。
2.探索自己不熟悉的算法和数据结构ACM竞赛中考察的算法不限于常见的算法,还包括各种数论、图论、动态规划等。
掌握这些算法和数据结构可以提高解题的速度和质量。
在掌握新算法之前,阅读相关论文或文章,掌握其基本原理和实现方法。
ACM常用算法模板
专用模板目录:一、图论1.最大团2.拓扑排序3.最短路和次短路4.SAP模板5.已知各点度,问能否组成一个简单图6.KRUSKAL7. Prim算法求最小生成树8. Dijkstra9 . Bellman-ford10. SPFA11. Kosaraju 模板12. tarjan 模板二、数学1. 剩余定理2. N!中质因子P的个数3.拓展欧几里得4.三角形的各中心到顶点的距离和5.三角形外接圆半径周长6.归并排序求逆序数7. 求N!的位数8.欧拉函数9. Miller-Rabin,大整数分解,求欧拉函数10. 第一类斯特林数11.计算表达式12.约瑟夫问题13.高斯消元法14. Baby-step,giant-step n是素数.n任意15. a^b%c=a ^(b%eular(c)+eular(c)) % c16.判断第二类斯特林数的奇偶性17.求组合数C(n,r)18.进制转换19.Ronberg算法计算积分20.行列式计算21. 返回x 的二进制表示中从低到高的第i位22.高精度运算 +-*/23.超级素数筛选三、数据结构1.树状数组2.线段树求区间的最大、小值3.线段树求区间和4.单调队列5.KMP模板6. 划分树,求区间第k小数7.最大堆,最小堆模板8. RMQ模板求区间最大、最小值9.快速排序,归并排序求逆序数.10.拓展KMP四、计算几何1.凸包面积2.Pick公式求三角形内部有多少点3.多边形边上内部各多少点以及面积pick4.平面最远点对5.判断矩形是否在矩形内6.判断点是否在多边形内7.判断4个点(三维)是否共面8.凸包周长9.等周定理变形一直两端点和周长求最大面积10.平面最近点对11.单位圆最多覆盖多少点(包括边上)12.多边形费马点求点到多边形各个点的最短距离13.矩形并周长14.zoj 2500 求两球体积并一、图论1.最大团#include<iostream>#include<algorithm>using namespace std;int n,m;int cn;//当前顶点数int best;//当前最大顶点数int vis[50];//当前解int bestn[50];//最优解int map[50][50];//临界表void dfs(int i){if(i>n){for(int j=1;j<=n;j++) bestn[j]=vis[j];best=cn;return ;}int ok=1;for(int j=1;j<i;j++){if(vis[j]==1&&map[i][j]==0){ok=0;break;}}if(ok){//进入左子树vis[i]=1;cn++;dfs(i+1);cn--;}if(cn+n-i>best){//进入右子树vis[i]=0;dfs(i+1);}}int main(){while(scanf("%d%d",&n,&m)==2){memset(vis,0,sizeof(vis));memset(map,0,sizeof(map));while(m--){int p,q;scanf("%d%d",&p,&q);map[p][q]=map[q][p]=1;//无向图}cn=0;best=0;dfs(1);printf("%d\n",best);}return 0;}2.拓扑排序#include<iostream>#include<cstring>using namespace std;int map[105][105],in[105],vis[105],ans[105],n;int flag;void dfs(int step){if(flag) return ;if(step==n+1) {flag=1; printf("%d",ans[1]);for(int i=2;i<=n;i++) printf(" %d",ans[i]);printf("\n");return ;}for(int i=1;i<=n;i++){if(vis[i]==0&&in[i]==0){vis[i]=1;for(int j=1;j<=n;j++){if(map[i][j]>0){map[i][j]=-map[i][j];in[j]--;}}ans[step]=i;dfs(step+1);vis[i]=0;for(int j=1;j<=n;j++){if(map[i][j]<0){map[i][j]=-map[i][j];in[j]++;}}}}}int main(){while(scanf("%d",&n)==1){flag=0;memset(map,0,sizeof(map));memset(vis,0,sizeof(vis));memset(in,0,sizeof(in));for(int i=1;i<=n;i++){int t;while(scanf("%d",&t),t){map[i][t]=1;in[t]++;}}dfs(1);}return 0;}3.最短路和次短路#include<iostream>#include<cstdio>#include<vector>#include<cstring>using namespace std;class Node{public:int e,w;//表示终点和边权};const int inf=(1<<25);int main(){int ci;cin>>ci;while(ci--){vector<Node> G[1005];//用邻接表存边int n,m;cin>>n>>m;for(int i=1;i<=m;i++){Node q;int u;cin>>u>>q.e>>q.w;G[u].push_back(q);}int s,f;//起点和终点cin>>s>>f;//dijkstra 求最短路和次短路int flag[1005][2];int dis[1005][2],cnt[1005][2];//0表示最短路,1表示次短路memset(flag,0,sizeof(flag));for(int i=1;i<=n;i++) dis[i][0]=dis[i][1]=inf;dis[s][0]=0;cnt[s][0]=1;//初始化for(int c=0;c<2*n;c++) //找最短路和次短路,故要进行2*n次循环也可以改成while(1){int temp=inf,u=-1,k;//找s-S'集合中的最短路径,u记录点的序号,k记录是最短路或者是次短路for(int j=1;j<=n;j++){if(flag[j][0]==0&&temp>dis[j][0]) temp=dis[j][0],u=j,k=0;else if(flag[j][1]==0&&temp>dis[j][1]) temp=dis[j][1],u=j,k=1;}if(temp==inf) break;//S'集合为空或者不联通,算法结束//更新路径flag[u][k]=1;for(int l=0;l<G[u].size();l++){int d=dis[u][k]+G[u][l].w,j=G[u][l].e;//important//4种情况if(d<dis[j][0]){dis[j][1]=dis[j][0];cnt[j][1]=cnt[j][0];dis[j][0]=d;cnt[j][0]=cnt[u][k];}else if(d==dis[j][0]){cnt[j][0]+=cnt[u][k];}else if(d<dis[j][1]){dis[j][1]=d;cnt[j][1]=cnt[u][k];}else if(d==dis[j][1]){cnt[j][1]+=cnt[u][k];}}}int num=cnt[f][0];//最短路int cc=cnt[f][1];//次短路}return 0;}4.SAP模板#include<iostream>#include<cstdio>#include<cstring>using namespace std;const int inf=(1<<31)-1;const int point_num=300;int cap[point_num][point_num],dist[point_num],gap[point_num];//初始化见main里面int s0,t0,n;//源,汇和点数int find_path(int p,int limit=0x3f3f3f3f){if(p==t0) return limit;for(int i=0;i<n;i++)if(dist[p]==dist[i]+1 && cap[p][i]>0){int t=find_path(i,min(cap[p][i],limit));if(t<0) return t;if(t>0){cap[p][i]-=t;cap[i][p]+=t;return t;}}int label=n;for(int i=0;i<n;i++) if(cap[p][i]>0) label=min(label,dist[i]+1);if(--gap[dist[p]]==0 || dist[s0]>=n ) return -1;++gap[dist[p]=label];return 0;}int sap(){//初始化s,ts0=0,t0=n-1;int t=0,maxflow=0;gap[0]=n;while((t=find_path(s0))>=0) maxflow+=t;return maxflow;}int main(){int ci;while(cin>>ci>>n){//初始化memset(cap,0,sizeof(cap));memset(dist,0,sizeof(dist));memset(gap,0,sizeof(gap));//初始化capwhile(ci--){int x,y,c;cin>>x>>y>>c;x--;y--;cap[x][y]+=c;//因题而异}int ans=sap();cout<<ans<<endl;}return 0;}5.已知各点度,问能否组成一个简单图#include<iostream>#include<cstdio>#include<algorithm>using namespace std;const int inf=(1<<30);int d[1100];bool cmp(int x,int y){return x>y;}int main(){int ci;scanf("%d",&ci);while(ci--){int n,flag=1,cnt=0;scanf("%d",&n); for(int i=0;i<n;i++){scanf("%d",&d[i]);if(d[i]>n-1||d[i]<=0) flag=0; cnt+=d[i];}if(flag==0||cnt%2){printf("no\n");continue;}sort(d,d+n,cmp);for(int l=n;l>0;l--){for(int i=1;i<l&&d[0];i++){d[0]--,d[i]--;if(d[i]<0){flag=0;break;}}if(d[0]) flag=0;if(flag==0) break;d[0]=-inf;sort(d,d+l,cmp);}if(flag) printf("yes\n");else printf("no\n");}return 0;}6.KRUSKAL#include<iostream>#include<algorithm>using namespace std;int u[15005],v[15005],w[15005],fath[15005],r[15005];int ans1[15005],ans2[15005];bool cmp(int i,int j){return w[i]<w[j];}int find(int x){return fath[x]==x?x:fath[x]=find(fath[x]);}int main(){int n,m;cin>>n>>m;for(int i=1;i<=n;i++) fath[i]=i;for(int i=1;i<=m;i++) r[i]=i;for(int i=1;i<=m;i++){cin>>u[i]>>v[i]>>w[i];}sort(r+1,r+m+1,cmp);int maxn=0,ans=0,k=0;for(int i=1;i<=m;i++){int e=r[i];int x=find(u[e]),y=find(v[e]);if(x!=y){ans+=w[e];fath[x]=y;if(w[e]>maxn) maxn=w[e];ans1[k]=u[e];ans2[k++]=v[e];}}return 0;}7.prime求最小生成树语法:prim(Graph G,int vcount,int father[]);参数:G:图,用邻接矩阵表示vcount:表示图的顶点个数father[]:用来记录每个节点的父节点返回值:null注意:常数max_vertexes 为图最大节点数常数infinity为无穷大源程序:#define infinity 1000000#define max_vertexes 5typedef int Graph[max_vertexes][max_vertexes];void prim(Graph G,int vcount,int father[]){int i,j,k;intlowcost[max_vertexes],closeset[max_vertexes],used[max_vertexes]; for (i=0;i<vcount;i++){lowcost[i]=G[0][i];closeset[i]=0;used[i]=0;father[i]=-1;}used[0]=1;for (i=1;i<vcount;i++){j=0;while (used[j]) j++;for (k=0;k<vcount;k++)if ((!used[k])&&(lowcost[k]<lowcost[j])) j=k;father[j]=closeset[j];used[j]=1;for (k=0;k<vcount;k++)if (!used[k]&&(G[j][k]<lowcost[k])){ lowcost[k]=G[j][k];closeset[k]=j; }}}8.Dijkstra语法:result=Dijkstra(Graph G,int n,int s,int t, int path[]); 参数:G:图,用邻接矩阵表示n:图的顶点个数s:开始节点t:目标节点path[]:用于返回由开始节点到目标节点的路径返回值:最短路径长度注意:输入的图的权必须非负顶点标号从0 开始用如下方法打印路径:i=t;while (i!=s){printf("%d<--",i+1);i=path[i];}printf("%d\n",s+1);源程序:int Dijkstra(Graph G,int n,int s,int t, int path[]){int i,j,w,minc,d[max_vertexes],mark[max_vertexes];for (i=0;i<n;i++) mark[i]=0;for (i=0;i<n;i++){ d[i]=G[s][i];path[i]=s; }mark[s]=1;path[s]=0;d[s]=0;for (i=1;i<n;i++){minc=infinity;w=0;for (j=0;j<n;j++)if ((mark[j]==0)&&(minc>=d[j])) {minc=d[j];w=j;}mark[w]=1;for (j=0;j<n;j++)if((mark[j]==0)&&(G[w][j]!=infinity)&&(d[j]>d[w]+G[w][j])){ d[j]=d[w]+G[w][j];path[j]=w; }}return d[t];}9.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 开始用如下方法打印路径:i=t;while (i!=s){printf("%d<--",i+1);i=path[i];}printf("%d\n",s+1);源程序:int Bellman_ford(Graph G,int n,int s,int t,int path[],int success){int i,j,k,d[max_vertexes];for (i=0;i<n;i++) {d[i]=infinity;path[i]=0;}d[s]=0;for (k=1;k<n;k++)for (i=0;i<n;i++)for (j=0;j<n;j++)if (d[j]>d[i]+G[i][j]){d[j]=d[i]+G[i][j];path[j]=i;}success=0;for (i=0;i<n;i++)for (j=0;j<n;j++)if (d[j]>d[i]+G[i][j]) return 0;success=1;return d[t];}10. SPFA#include<iostream>#include<cstdio>#include<cstring>#include<vector>using namespace std;const __int64 maxn=1001000;const __int64 inf=1000100000;struct edge//邻接表{__int64 t,w;//s->t=w;__int64 next;//数组模拟指针};__int64 p[maxn],pf[maxn];//邻接表头节点edge G[maxn],Gf[maxn];//邻接表__int64 V,E;//点数[1-n] 边数__int64 dis[maxn];__int64 que[maxn],fro,rear;//模拟队列__int64 vis[maxn];__int64 inque[maxn];//入队次数bool spfa(__int64 s0){fro=rear=0;for(__int64 i=1;i<=V;i++) dis[i]=inf;dis[s0]=0;memset(vis,0,sizeof(vis));memset(inque,0,sizeof(inque));que[rear++]=s0;vis[s0]=1;inque[s0]++;while(fro!=rear){__int64 u=que[fro];fro++;if(fro==maxn) fro=0;vis[u]=0;for(__int64 i=p[u];i!=-1;i=G[i].next){__int64 s=u,t=G[i].t,w=G[i].w;if(dis[t]>dis[s]+w){dis[t]=dis[s]+w;if(vis[t]==0){que[rear++]=t,vis[t]=1;inque[t]++;if(inque[t]>V) return false;if(rear==maxn) rear=0;}}}}return true;}int main(){__int64 ci;scanf("%I64d",&ci);while(ci--){scanf("%I64d%I64d",&V,&E);memset(p,-1,sizeof(p));memset(pf,-1,sizeof(pf)); for(__int64 i=0;i<E;i++){__int64 u,v,w;scanf("%I64d%I64d%I64d",&u,&v,&w);G[i].t=v;G[i].w=w;G[i].next=p[u];p[u]=i;Gf[i].t=u;Gf[i].w=w;Gf[i].next=pf[v];pf[v]=i;}__int64 ans=0;spfa(1);//求第一个点到其他点的最短距离和for(__int64 i=1;i<=V;i++) ans+=dis[i];//反方向再来一次spfa 求其他点到第一个点的最短距离和 for(__int64 i=1;i<=V;i++) p[i]=pf[i];for(__int64 i=0;i<E;i++) G[i]=Gf[i];spfa(1);for(__int64 i=1;i<=V;i++) ans+=dis[i];printf("%I64d\n",ans);}return 0;}11.Kosaraju模板#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn=100000;struct edge{int t,w;//u->t=w;int next;};int V,E;//点数(从1开始),边数int p[maxn],pf[maxn];//邻接表原图,逆图edge G[maxn],Gf[maxn];//邻接表原图,逆图int l,lf;void init(){memset(p,-1,sizeof(p));memset(pf,-1,sizeof(pf));l=lf=0;}void addedge(int u,int t,int w,int l){G[l].w=w;G[l].t=t;G[l].next=p[u];p[u]=l;}void addedgef(int u,int t,int w,int lf){Gf[l].w=w;Gf[l].t=t;Gf[l].next=pf[u];pf[u]=l;}///Kosaraju算法,返回为强连通分量个数bool flag[maxn]; //访问标志数组int belg[maxn]; //存储强连通分量,其中belg[i]表示顶点i属于第belg[i]个强连通分量int numb[maxn]; //结束时间(出栈顺序)标记,其中numb[i]表示离开时间为i的顶点//用于第一次深搜,求得numb[1..n]的值void VisitOne(int cur, int &sig){flag[cur] = true;for (int i=p[cur];i!=-1;i=G[i].next){if (!flag[G[i].t]){VisitOne(G[i].t,sig);}}numb[++sig] = cur;}//用于第二次深搜,求得belg[1..n]的值void VisitTwo(int cur, int sig){flag[cur] = true;belg[cur] = sig;for (int i=pf[cur];i!=-1;i=Gf[i].next){if (!flag[Gf[i].t]){VisitTwo(Gf[i].t,sig);}}//Kosaraju算法,返回为强连通分量个数int Kosaraju_StronglyConnectedComponent(){int i, sig;//第一次深搜memset(flag,0,sizeof(flag));for ( sig=0,i=1; i<=V; ++i ){if ( false==flag[i] ){VisitOne(i,sig);}}//第二次深搜memset(flag,0,sizeof(flag));for ( sig=0,i=V; i>0; --i ){if ( false==flag[numb[i]] ){VisitTwo(numb[i],++sig);}}return sig;}int main(){while(scanf("%d",&V)==1){init();for(int i=1;i<=V;i++){int u=i,t,w=1;while(scanf("%d",&t)==1&&t){E++;addedge(u,t,w,l++);addedgef(t,u,w,lf++);}}int ans=Kosaraju_StronglyConnectedComponent(); printf("%d\n",ans);}return 0;12.tarjan模板//自己模板#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn=100000;int V,E;//点数(1) 边数struct edge//邻接表{int t,w;//u->t=w;int next;};int p[maxn];//表头节点edge G[maxn];int l;void init(){memset(p,-1,sizeof(p));l=0;}//添加边void addedge(int u,int t,int w,int l)//u->t=w;{G[l].w=w;G[l].t=t;G[l].next=p[u];p[u]=l;}//tarjan算法求有向图强联通分量int dfn[maxn],lowc[maxn];//dfn[u]节点u搜索的次序编号,lowc[u]u或者u的子树能够追溯到的栈中的最早的节点int belg[maxn];//第i个节点属于belg[i]个强连通分量int stck[maxn],stop;//stck栈int instck[maxn];//第i个节点是否在栈中int scnt;//强联通分量int index;void dfs(int i){dfn[i]=lowc[i]=++index;instck[i]=1;//节点i入栈stck[++stop]=i;for(int j=p[i];j!=-1;j=G[j].next){int t=G[j].t;//更新lowc数组if(!dfn[t])//t没有遍历过{dfs(t);if(lowc[i]>lowc[t]) lowc[i]=lowc[t];}//t是i的祖先节点else if(instck[t]&&lowc[i]>dfn[t]) lowc[i]=dfn[t];}//是强连通分量的根节点if(dfn[i]==lowc[i]){scnt++;int t;do{t=stck[stop--];instck[t]=0;belg[t]=scnt;}while(t!=i);}}int tarjan(){stop=scnt=index=0;memset(dfn,0,sizeof(dfn));memset(instck,0,sizeof(instck));for(int i=1;i<=V;i++){if(!dfn[i]) dfs(i);}return scnt;}int main(){while(scanf("%d",&V)==1){init();for(int i=1;i<=V;i++){int x;while(scanf("%d",&x)==1&&x){E++;addedge(i,x,1,l++);}}int ans=tarjan();printf("%d\n",ans);}return 0;}//吉大模板邻接表版#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn=100000;int V,E;//点数(1) 边数struct edge//邻接表{int t,w;//u->t=w;int next;};int p[maxn];//表头节点edge G[maxn];int l;void init(){memset(p,-1,sizeof(p));l=0;}//添加边void addedge(int u,int t,int w,int l)//u->t=w;{G[l].w=w;G[l].t=t;G[l].next=p[u];p[u]=l;}//tarjan算法求有向图强联通分量int dfn[maxn],lowc[maxn];//dfn[u]节点u搜索的次序编号,lowc[u]u或者u的子树能够追溯到的栈中的最早的节点int stck[maxn],stop;//stck栈int pre[maxn];//int scnt;//强联通分量int cnt;//void dfs(int v)//1-V{int t,minc=lowc[v]=pre[v]=cnt++;stck[stop++]=v;for(int i=p[v];i!=-1;i=G[i].next){int pv=G[i].t;if(pre[pv]==-1) dfs(pv);if(lowc[pv]<minc) minc=lowc[pv]; }if(minc<lowc[v]){lowc[v]=minc;return ;}do{dfn[t=stck[--stop]]=scnt;lowc[t]=V;}while(t!=v);++scnt;}int tarjan(){stop=cnt=scnt=0;memset(pre,-1,sizeof(pre));for(int i=1;i<=V;i++){if(pre[i]==-1) dfs(i);}return scnt;}int main(){while(scanf("%d",&V)==1){init();for(int i=1;i<=V;i++){int x;while(scanf("%d",&x)==1&&x){E++;addedge(i,x,1,l++);}}int ans=tarjan();printf("%d\n",ans);}return 0;}二、数学1.剩余定理int mod(int c[],int b[],int n){int all_multy=1,sum=0;int i,j,x[5];for(i=0;i<n;i++)all_multy*=c[i];for(i=0;i<n;i++)x[i]=all_multy/c[i];for(i=0;i<n;i++){j=1;while((x[i]*j)%c[i]!=1)j++;x[i]*=j;}for(i=0;i<n;i++)sum+=(b[i]*x[i]);return sum%all_multy;}2.N!中质因子P的个数//对于任意质数p,n!中有(n/p+n/p^2+n/p^3+...)个质因子p。
个人整理 ACM 模板
0.头文件#define _CRT_SBCURE_NO_DEPRECATE #include <set>#include <cmath>#include <queue>#include <stack>#include <vector>#include <string>#include <cstdio>#include <cstdlib>#include <cstring>#include <iostream>#include <algorithm>#include <functional>using namespace std;const int maxn = 110;1.const int INF = 0x3f3f3f3f;经典1.埃拉托斯特尼筛法/*|埃式筛法||快速筛选素数||16/11/05ztx|*/int prime[maxn];bool is_prime[maxn];int sieve(int n){int p = 0;for(int i = 0; i <= n; ++i)is_prime[i] = true;is_prime[0] = is_prime[1] = false;for (int i = 2; i <= n; ++i){ // 注意数组大小是nif(is_prime[i]){prime[p++] = i;for(int j = i + i; j <= n; j += i) // 轻剪枝,j必定是i的倍数is_prime[j] = false;}}return p; // 返回素数个数}2.快速幂/*|快速幂||16/11/05ztx|*/typedef long long LL; // 视数据大小的情况而定LL powerMod(LL x, LL n, LL m){LL res = 1;while (n > 0){if (n & 1) // 判断是否为奇数,若是则true res = (res * x) % m;x = (x * x) % m;n >>= 1; // 相当于n /= 2;}return res;}3.大数模拟大数加法/*|大数模拟加法||用string模拟||16/11/05ztx, thanks to caojiji|*/string add1(string s1, string s2){if (s1 == "" && s2 == "") return"0";if (s1 == "") return s2;if (s2 == "") return s1;string maxx = s1, minn = s2;if (s1.length() < s2.length()){maxx = s2;minn = s1;}int a = maxx.length() - 1, b = minn.length() - 1;for (int i = b; i >= 0; --i){maxx[a--] += minn[i] - '0'; // a一直在减,额外还要减个'0'}for (int i = maxx.length()-1; i > 0;--i){ if (maxx[i] > '9'){maxx[i] -= 10;//注意这个是减10maxx[i - 1]++;}}if (maxx[0] > '9'){maxx[0] -= 10;maxx = '1' + maxx;}return maxx;}大数阶乘/*|大数模拟阶乘||用数组模拟||16/12/02ztx|*/#include <iostream>#include <cstdio>using namespace std;typedef long long LL;const int maxn = 100010;int num[maxn], len;/*在mult函数中,形参部分:len每次调用函数都会发生改变,n 表示每次要乘以的数,最终返回的是结果的长度tip: 阶乘都是先求之前的(n-1)!来求n!初始化Init函数很重要,不要落下*/void Init() {len = 1;num[0] = 1;}int mult(int num[], int len, int n) {LL tmp = 0;for(LL i = 0; i < len; ++i) {tmp = tmp + num[i] * n; //从最低位开始,等号左边的tmp表示当前位,右边的tmp表示进位(之前进的位)num[i] = tmp % 10; // 保存在对应的数组位置,即去掉进位后的一位数tmp = tmp / 10; // 取整用于再次循环,与n和下一个位置的乘积相加}while(tmp) { // 之后的进位处理num[len++] = tmp % 10;tmp = tmp / 10;}return len;}int main() {Init();int n;n = 1977; // 求的阶乘数for(int i = 2; i <= n; ++i) {len = mult(num, len, i);}for(int i = len - 1; i >= 0; --i)printf("%d",num[i]); // 从最高位依次输出,数据比较多采用printf输出printf("\n");return0;}4.GCD/*|辗转相除法||欧几里得算法||求最大公约数||16/11/05ztx|*/int gcd(int big, int small){if (small > big) s, small);int temp;while (small != 0){ // 辗转相除法if (small > big) s, small); temp = big % small;big = small;small = temp;}return(big);}5.LCM/*|辗转相除法||欧几里得算法||求最小公倍数||16/11/05ztx|*/int gcd(int big, int small){if (small > big) s, small);int temp;while (small != 0){ // 辗转相除法if (small > big) s, small);temp = big % small;big = small;small = temp;}return(big);}6.全排列/*|求1到n的全排列, 有条件||16/11/05ztx, thanks to wangqiqi|*/void Pern(int list[], int k, int n) { // k表示前k 个数不动仅移动后面n-k位数if (k == n - 1) {for (int i = 0; i < n; i++) {printf("%d", list[i]);}printf("\n");}else {for (int i = k; i < n; i++) { // 输出的是满足移动条件所有全排列s[k], list[i]);Pern(list, k + 1, n);s[k], list[i]);}}}7.二分搜索/*|二分搜索||要求:先排序||16/11/05ztx, thanks to wangxiaocai|*/// left为最开始元素, right是末尾元素的下一个数,x是要找的数int bsearch(int *A, int left, int right, int x){int m;while (left < right){m = left + (right - left) / 2;if (A[m] >= x) right = m; else left = m + 1;// 如果要替换为 upper_bound, 改为:if(A[m] <= v) x = m+1; else y = m;}return left;}/*最后left == right如果没有找到135577找6,返回7如果找有多少的x,可以用lower_bound查找一遍,upper_bound查找一遍,下标相减C++自带的lower_bound(a,a+n,x)返回数组中最后一个x的下一个数的地址upper_bound(a,a+n,x)返回数组中第一个x的地址如果a+n内没有找到x或x的下一个地址,返回a+n的地址lower_bound(a,a+n,x)-upper_bound(a,a+n,x)返回数组中x的个数*/数据结构并查集8.并查集/*|合并节点操作||16/11/05ztx, thanks to chaixiaojun|*/int father[maxn]; // 储存i的father父节点void makeSet() {for (int i = 0; i < maxn; i++)father[i] = i;}int findRoot(int x) { // 迭代找根节点int root = x; // 根节点while (root != father[root]) { // 寻找根节点root = father[root];}while (x != root) {int tmp = father[x];father[x] = root; // 根节点赋值x = tmp;}return root;}void Union(int x, int y) { // 将x所在的集合和y所在的集合整合起来形成一个集合。
核心算法——ACM模板
核心算法——ACM模板一、贪心算法 (2)1、区间选点 (2)2、区间覆盖 (2)3、不相交区间 (2)4、哈夫曼编码 (2)5、最小值最大化、最大值最小化(二分查找) (2)二、动态规划 (5)1、最长公共子序列(LCS) (5)2、最长上升公共子序列(LIS) (7)3、子段和 (9)4、DAG上的动态规划 (13)5、区间DP (17)6、状态压缩DP (24)7、双线DP (30)8、背包问题(见背包九讲) (32)三、数据结构 (32)1、并查集 (32)2、树状数组 (34)3、(字符串)KMP匹配 (37)四、最小生成树算法 (41)Prime核心算法 (41)Kruskal算法 (44)五、单源最短路径 (50)Dijkstra核心算法 (50)Bellman_Ford算法 (54)SPFA算法(Bellman_Ford的队列实现) (58)六、二分图匹配 (61)1、匈牙利算法 (61)七、网络流 (63)1、SAP算法 (64)2、Dinic算法 (68)一、贪心算法1、区间问题区间选点选取尽量少的点覆盖所有的区间,是每个区间至少包含一个点。
对区间右端点进行排序。
区间覆盖选取尽量少的区间覆盖整个区域。
对左端点进行排序。
不相交区间选取尽量多的不相交区间。
对区间右端点进行排序。
2、哈夫曼编码3、最小值最大化、最大值最小化(二分查找)NYOJ 疯牛问题(最小值最大化)农夫John 建造了一座很长的畜栏,它包括N (2 <= N <= 100,000)个隔间,这些小隔间依次编号为x1,...,xN (0 <= xi <= 1,000,000,000).但是,John的C (2 <= C <= N)头牛们并不喜欢这种布局,而且几头牛放在一个隔间里,他们就要发生争斗。
为了不让牛互相伤害。
John决定自己给牛分配隔间,使任意两头牛之间的最小距离尽可能的大,那么,这个最大的最小距离是什么呢?#include#include#includeusing namespace std;int n, c;int pos[100005];bool judge(int k){int cnt = 1;int st = pos[0];for(int i = 1; i < n; ++i){if(pos[i] - st >= k){++cnt;if(cnt >= c)return true;st = pos[i];}}return false;}int Binary_search(int left, int right) /// 二分枚举满足条件的最大距离{while(left <= right){int mid = (left + right) >> 1;if(judge(mid)) /// 所求距离 >= mid,可以继续增大试探left = mid+1;else /// 所求距离 < mid,所以必须减小来试探right = mid-1;}return left-1;}int main(){while(~scanf("%d%d", &n, &c)){for(int i = 0; i < n; ++i)scanf("%d", &pos[i]);sort(pos, pos+n);printf("%d\n", Binary_search(0, pos[n-1] - pos[0]));}return 0;}NYOJ 摘枇杷(最大值最小化)理工学院的枇杷快熟了,ok,大家都懂得。
-【精品资料】ACM大赛必备_常用函数整理_ACM模板(整理版)
目录一、数学问题 (4)1.精度计算——大数阶乘 (4)2.精度计算——乘法(大数乘小数) (4)3.精度计算——乘法(大数乘大数) (5)4.精度计算——加法 (6)5.精度计算——减法 (7)6.任意进制转换 (8)7.最大公约数、最小公倍数 (9)8.组合序列 (10)9.快速傅立叶变换(FFT) (10)10.Ronberg 算法计算积分 (12)11.行列式计算 (14)12.求排列组合数 (15)13.求某一天星期几 (15)14.卡特兰(Catalan) 数列原理 (16)15.杨辉三角 (16)16.全排列 (17)17.匈牙利算法----最大匹配问题 (18)18.最佳匹配KM 算法 (20)二、字符串处理 (22)1.字符串替换 (22)2.字符串查找 (23)3.字符串截取 (24)4.LCS-最大公共子串长度 (24)5.LCS-最大公共子串长度 (25)6.数字转换为字符 (26)三、计算几何 (27)1.叉乘法求任意多边形面积 (27)2.求三角形面积 (27)3.两矢量间角度 (28)4.两点距离(2D、3D) (28)5.射向法判断点是否在多边形内部 (29)6.判断点是否在线段上 (30)7.判断两线段是否相交 (31)8.判断线段与直线是否相交 (32)9.点到线段最短距离 (32)10.求两直线的交点 (33)11.判断一个封闭图形是凹集还是凸集 (34)12.Graham 扫描法寻找凸包 (35)13.求两条线段的交点 (36)四、数论 (37)1.x 的二进制长度 (37)2.返回x 的二进制表示中从低到高的第i 位 (38)3.模取幂运算 (38)4.求解模线性方程 (39)5.求解模线性方程组(中国余数定理) (39)6.筛法素数产生器 (40)7.判断一个数是否素数 (41)8.求距阵最大和 (42)8.求一个数每一位相加之和 (43)10.质因数分解 (43)11.高斯消元法解线性方程组 (44)五、图论 (45)1.Prim 算法求最小生成树................................................. 45 2.Dijkstra 算法求单源最短路径.. (46)3.Bellman-ford 算法求单源最短路径 (47)4.Floyd-Warshall 算法求每对节点间最短路径 (48)5.解欧拉图 (49)六、排序/查找 (50)1.快速排序 (50)2.希尔排序 (51)3.选择法排序 (52)4.二分查找 (52)七、数据结构 (53)1.顺序队列 (53)2.顺序栈 (56)3.链表 (59)4.链栈 (63)5.二叉树 (66)八、高精度运算专题 (68)1.专题函数说明 (68)2.高精度数比较 (69)3.高精度数加法 (69)4.高精度数减法 (70)5.高精度乘10 (71)6.高精度乘单精度 (71)7.高精度乘高精度 (72)8.高精度除单精度 (72)9.高精度除高精度 (73)九、标准模板库的使用 (74)1.计算求和 (74)2.求数组中的最大值 (76)3. sort 和qsort (76)十、其他 (78)1.运行时间计算 (78)DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD一、数学问题1.精度计算——大数阶乘语法:int result=factorial(int n);参数:n:n 的阶乘返回值:阶乘结果的位数注意:本程序直接输出n!的结果,需要返回结果请保留long a[] 需要math.h源程序:int factorial(int n){long a[10000];int i,j,l,c,m=0,w;a[0]=1;for(i=1;i<=n;i++){c=0;for(j=0;j<=m;j++){a[j]=a[j]*i+c;c=a[j]/10000;a[j]=a[j]%10000;}if(c>0) {m++;a[m]=c;}}w=m*4+log10(a[m])+1;printf("\n%ld",a[m]);for(i=m-1;i>=0;i--) printf("%4.4ld",a[i]);return w;}我也可以做到..5 / 782.精度计算——乘法(大数乘小数)语法:mult(char c[],char t[],int m);参数:c[]:被乘数,用字符串表示,位数不限t[]:结果,用字符串表示m:乘数,限定10 以内返回值:null注意:需要string.h源程序:void mult(char c[],char t[],int m){int i,l,k,flag,add=0;char s[100];l=strlen(c);for (i=0;i<l;i++)s[l-i-1]=c[i]-'0';for (i=0;i<l;i++){k=s[i]*m+add;if (k>=10) {s[i]=k%10;add=k/10;flag=1;} else{s[i]=k;flag=0;add=0;}}if (flag) {l=i+1;s[i]=add;} else l=i;for (i=0;i<l;i++)t[l-1-i]=s[i]+'0'; t[l]='\0';}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[]){我也可以做到..6 / 78int i,j,k=0,alen,blen,sum=0,res[65][65]={0},flag=0; char result[65];alen=strlen(a);blen=strlen(b);for (i=0;i<alen;i++)for (j=0;j<blen;j++) res[i][j]=(a[i]-'0')*(b[j]-'0');for (i=alen-1;i>=0;i--){for (j=blen-1;j>=0;j--) sum=sum+res[i+blen-j-1][j]; result[k]=sum%10;k=k+1;sum=sum/10;}for (i=blen-2;i>=0;i--){for (j=0;j<=i;j++) sum=sum+res[i-j][j];result[k]=sum%10;k=k+1;sum=sum/10;}if (sum!=0) {result[k]=sum;k=k+1;}for (i=0;i<k;i++) result[i]+='0';for (i=k-1;i>=0;i--) s[i]=result[k-1-i];s[k]='\0';while(1){if (strlen(s)!=strlen(a)&&s[0]=='0')strcpy(s,s+1);elsebreak;}}4.精度计算——加法语法:add(char a[],char b[],char s[]);参数:a[]:被加数,用字符串表示,位数不限b[]:加数,用字符串表示,位数不限s[]:结果,用字符串表示返回值:null注意:空间复杂度为o(n^2)我也可以做到..7 / 78需要string.hDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD源程序:void add(char a[],char b[],char back[]){int i,j,k,up,x,y,z,l;char *c;if (strlen(a)>strlen(b)) l=strlen(a)+2; else l=strlen(b)+2; c=(char *) malloc(l*sizeof(char));i=strlen(a)-1;j=strlen(b)-1;k=0;up=0;while(i>=0||j>=0){if(i<0) x='0'; else x=a[i];if(j<0) y='0'; else y=b[j];z=x-'0'+y-'0';if(up) z+=1;if(z>9) {up=1;z%=10;} else up=0;c[k++]=z+'0';i--;j--;}if(up) c[k++]='1';i=0;c[k]='\0';for(k-=1;k>=0;k--)back[i++]=c[k];back[i]='\0';}5.精度计算——减法语法:sub(char s1[],char s2[],char t[]);参数:s1[]:被减数,用字符串表示,位数不限s2[]:减数,用字符串表示,位数不限t[]:结果,用字符串表示返回值:null注意:默认s1>=s2,程序未处理负数情况需要string.h源程序:void sub(char s1[],char s2[],char t[])我也可以做到..8 / 78{int i,l2,l1,k;l2=strlen(s2);l1=strlen(s1);t[l1]='\0';l1--;for (i=l2-1;i>=0;i--,l1--){if (s1[l1]-s2[i]>=0)t[l1]=s1[l1]-s2[i]+'0';else{t[l1]=10+s1[l1]-s2[i]+'0';s1[l1-1]=s1[l1-1]-1;}}k=l1;while(s1[k]<0) {s1[k]+=10;s1[k-1]-=1;k--;}while(l1>=0) {t[l1]=s1[l1];l1--;}loop:if (t[0]=='0') {l1=strlen(s1);for (i=0;i<l1-1;i++) t[i]=t[i+1];t[l1-1]='\0';goto loop;}if (strlen(t)==0) {t[0]='0';t[1]='\0';}}6.任意进制转换语法:conversion(char s1[],char s2[],char t[]);参数:s[]:转换前的数字s2[]:转换后的数字d1:原进制数d2:需要转换到的进制数返回值:null注意:高于9 的位数用大写'A'~'Z'表示,2~16 位进制通过验证源程序:void conversion(char s[],char s2[],long d1,long d2){我也可以做到..9 / 78long i,j,t,num;char c;num=0;for (i=0;s[i]!='\0';i++){if (s[i]<='9'&&s[i]>='0') t=s[i]-'0'; else t=s[i]-'A'+10;num=num*d1+t;}i=0;while(1){t=num%d2;if (t<=9) s2[i]=t+'0'; else s2[i]=t+'A'-10;num/=d2;if (num==0) break;i++;}for (j=0;j<i/2;j++){c=s2[j];s2[j]=s[i-j];s2[i-j]=c;}s2[i+1]='\0';}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){int r=0;while(b!=0){r=a%b;a=b;DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDb=r;}return(a);我也可以做到..10 / 78}lcd(int u,int v,int h){return(u*v/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){int i,t;if(m1<0 || m1>n1) return;if(m1==n1){return;}m_of_n(m,n1-1,m1,a,head); // 递归调用t=a[head];a[head]=a[n1-1+head];a[n1-1+head]=t;m_of_n(m,n1-1,m1-1,a,head+1); // 再次递归调用t=a[head];a[head]=a[n1-1+head];a[n1-1+head]=t;}9.快速傅立叶变换(FFT)语法:kkfft(double pr[],double pi[],int n,int k,double fr[],double fi[],intl,int il);参数:我也可以做到..11 / 78pr[n]:输入的实部pi[n]:数入的虚部n,k:满足n=2^kfr[n]:输出的实部fi[n]:输出的虚部l:逻辑开关,0 FFT,1 ifFTil:逻辑开关,0 输出按实部/虚部;1 输出按模/幅角返回值:null注意:需要math.h源程序:void kkfft(pr,pi,n,k,fr,fi,l,il)int n,k,l,il;double pr[],pi[],fr[],fi[];{int it,m,is,i,j,nv,l0; double p,q,s,vr,vi,poddr,poddi;for (it=0; it<=n-1; it++){m=it; is=0;for (i=0; i<=k-1; i++){j=m/2; is=2*is+(m-2*j); m=j;}fr[it]=pr[is]; fi[it]=pi[is];}pr[0]=1.0; pi[0]=0.0;p=6.283185306/(1.0*n);pr[1]=cos(p); pi[1]=-sin(p);if (l!=0) pi[1]=-pi[1];for (i=2; i<=n-1; i++){p=pr[i-1]*pr[1];q=pi[i-1]*pi[1];s=(pr[i-1]+pi[i-1])*(pr[1]+pi[1]);pr[i]=p-q; pi[i]=s-p-q;}for (it=0; it<=n-2; it=it+2){vr=fr[it]; vi=fi[it];fr[it]=vr+fr[it+1]; fi[it]=vi+fi[it+1];fr[it+1]=vr-fr[it+1]; fi[it+1]=vi-fi[it+1]; }m=n/2; nv=2;for (l0=k-2; l0>=0; l0--){我也可以做到..12 / 78m=m/2; nv=2*nv;for (it=0; it<=(m-1)*nv; it=it+nv)for (j=0; j<=(nv/2)-1; j++){p=pr[m*j]*fr[it+j+nv/2];q=pi[m*j]*fi[it+j+nv/2];s=pr[m*j]+pi[m*j];s=s*(fr[it+j+nv/2]+fi[it+j+nv/2]); poddr=p-q; poddi=s-p-q;fr[it+j+nv/2]=fr[it+j]-poddr;fi[it+j+nv/2]=fi[it+j]-poddi;fr[it+j]=fr[it+j]+poddr;fi[it+j]=fi[it+j]+poddi;}}if (l!=0)for (i=0; i<=n-1; i++){fr[i]=fr[i]/(1.0*n);fi[i]=fi[i]/(1.0*n);}if (il!=0)for (i=0; i<=n-1; i++){pr[i]=sqrt(fr[i]*fr[i]+fi[i]*fi[i]);if (fabs(fr[i])<0.000001*fabs(fi[i])) {if ((fi[i]*fr[i])>0) pi[i]=90.0;else pi[i]=-90.0;}DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDelsepi[i]=atan(fi[i]/fr[i])*360.0/6.283185306;}return;}10.Ronberg 算法计算积分语法:result=integral(double a,double b);参数:a:积分上限b:积分下限我也可以做到..13 / 78function f:积分函数返回值:f 在(a,b)之间的积分值注意:function f(x)需要自行修改,程序中用的是sina(x)/x 需要math.h默认精度要求是1e-5源程序:double f(double x){return sin(x)/x; //在这里插入被积函数}double integral(double a,double b){double h=b-a;double t1=(1+f(b))*h/2.0;int k=1;double r1,r2,s1,s2,c1,c2,t2;loop:double s=0.0;double x=a+h/2.0;while(x<b){s+=f(x);x+=h;}t2=(t1+h*s)/2.0;s2=t2+(t2-t1)/3.0;if(k==1){k++;h/=2.0;t1=t2;s1=s2;goto loop;}c2=s2+(s2-s1)/15.0;if(k==2){c1=c2;k++;h/=2.0;t1=t2;s1=s2;goto loop;}r2=c2+(c2-c1)/63.0;if(k==3){r1=r2; c1=c2;k++;h/=2.0;t1=t2;s1=s2;我也可以做到..14 / 78goto loop;}while(fabs(1-r1/r2)>1e-5){ r1=r2;c1=c2;k++;h/=2.0;t1=t2;s1=s2;goto loop;}return r2;}11.行列式计算语法:result=js(int s[][],int n)参数:s[][]:行列式存储数组n:行列式维数,递归用返回值:行列式值注意:函数中常数N 为行列式维度,需自行定义源程序:int js(s,n)int s[][N],n;{int z,j,k,r,total=0;int b[N][N];/*b[N][N]用于存放,在矩阵s[N][N]中元素s[0]的余子式*/if(n>2){for(z=0;z<n;z++){for(j=0;j<n-1;j++)for(k=0;k<n-1;k++)if(k>=z) b[j][k]=s[j+1][k+1]; elseb[j][k]=s[j+1][k];if(z%2==0) r=s[0][z]*js(b,n-1); /*递归调用*/else r=(-1)*s[0][z]*js(b,n-1);total=total+r;}}else if(n==2)total=s[0][0]*s[1][1]-s[0][1]*s[1][0];return total;我也可以做到..15 / 78}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 p=1;while(m!=0){p*=n;n--;m--;}return p;}long C(long n,long m){long i,c=1;DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDi=m;while(i!=0){c*=n;n--;i--;}while(m!=0){c/=m;m--;}return c;}13.求某一天星期几语法:result=weekday(int N,int M,int d)参数:N,M,d:年月日,例如:2003,11,4返回值:0:星期天,1 星期一……注意:需要math.h适用于1582 年10 月15 日之后, 因为罗马教皇格里高利十三世在这一天启用新历法.源程序:我也可以做到..16 / 78int weekday(int N,int M,int d){int m,n,c,y,w;m=(M-2)%12;if (M>=3) n=N;else n=N-1;c=n/100;y=n%100;w=(int)(d+floor(13*m/5)+y+floor(y/4)+floor(c/4)-2*c)%7;while(w<0) w+=7;return w;}14.卡特兰(Catalan) 数列原理令h(1)=1,catalan 数满足递归式:h(n)= h(1)*h(n-1) + h(2)*h(n-2) + ... + h(n-1)h(1) (其中n>=2)该递推关系的解为:h(n)=c(2n-2,n-1)/n (n=1,2,3,...)1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, 58786, 208012, 742900, 2674440,9694845, 35357670, 129644790, 477638700, 1767263190, 6564120420,24466267020, 91482563640, 343059613650, 1289904147324, 4861946401452, …1.括号化问题。
ACM模板
next.Step_Counter=now.Step_Counter+1; // 计数器加1
if(CheckState(next)) // 如果状态满足约束条件则入队
{
int map[maxn][maxn]; // 坐标范围
int dir[4][2]= {0,1,0,-1,1,0,-1,0}; // 方向向量,(x,y)周围的四个方向
bool CheckEdge(int x,int y) // 边界条件和约束条件的判断
{
if(!vst[x][y] && ...) // 满足条件
return ans;
}
扩展欧几里德有什么用处呢?
求解形如 a*x +b*y = c 的通解,但是一般没有谁会无聊到让你写出一串通解出来,
都是让你在通解中选出一些特殊的解,比如一个数对于另一个数的乘法逆元
a*x=1(mod m)
这里,我们称 x 是 a 关于 m 的乘法逆元
memset(prime,0,sizeof(prime));
for(int i=2;i<=n;i++)
{
if(isprime[i])
{
prime[total]=i;
total++;
}
for(int j=0; j<total && i*prime[j]<=n; j++)
k = k%n;
if( k == 0 ) k=n;
d = (s+1) + (m-k);
ACM赛前准备——模板(排版篇)
ACM赛前准备 ——模板(排版篇)
ACM赛前准备——模板(排版篇)
更新
2018-01-31 添加中文支持
前言
一个好的模板抵的过一个漂亮的志愿者。本文旨在方便广大ACMer赛前整理代码,把繁琐的排版工作交给工具完成,更专 注于模板本身的内容。 再次强调:本文只谈排版,本文只谈排版,本文只谈排版。
பைடு நூலகம்Tex文件内容
照着抄就行了,不需要知道tex语法,里面已写好注释,增加模板只需要在tex中加个section就行。 实例:
1. % \twocolumn % 是否需要分栏显示 2. \newpage %另起一页 3. \section{String} %一级标题 4. \subsection{KMP} %二级标题 5. \inputminted[breaklines]{c++}{string/} %导入模板文件 6. \subsection{Suffix Automaton} 7. \inputminted[breaklines]{c++}{string/}
编译
1. xelatex -shell-escape ply-template.tex
相应目录下即可生成pdf文件
总结
用tex来创建ACM模板非常容易,只需要在tex文件中写好模板结构,把模板放在相应文件夹即可,相比较word,省去了大 量复制粘贴和排版的困难,并且代码和排版分离也使得模板的修改更为容易。
效果演示
封面
目录页
模板页(不分栏)
模板页(分栏)
结果文件
快速使用
1. git clone https:///palayutm/ply-template 2. cd ply-template 3. xelatex -shell-escape ply-template.tex
ACM模板
ACM模板---liang一.高精度计算: ------------------------------------------------------------ 31.高精度加法:----------------------------------------------------------- 31)C++ string类实现:----------------------------------------------- 3 2)字符数组char实现:----------------------------------------------- 32.高精度减法:----------------------------------------------------------- 41)C++ string类实现:------------------------------------------------ 4 2)字符数组char实现:------------------------------------------------ 53.高精度乘法------------------------------------------------------------- 51)字符数组char实现:------------------------------------------------ 5 2)C++ string类实现:------------------------------------------------ 64.高精度阶乘(压缩五位)------------------------------------------------- 65.高精度小数加法--------------------------------------------------------- 7 二.计算几何: -------------------------------------------------------------- 81.线段相交:------------------------------------------------------------- 82.点关于直线的对称点:点:(a,b),直线:Ax+By+C=0------------------------- 93.求凸包 ---------------------------------------------------------------- 94.多边形面积------------------------------------------------------------ 115.皮克定理:------------------------------------------------------------ 116.三角形: ------------------------------------------------------------- 121)点和三角形的关系------------------------------------------------- 12 2)三角形各种面积算法:--------------------------------------------- 137.两圆相交面积---------------------------------------------------------- 14 三.搜索: ------------------------------------------------------------------ 151.DFS(深度优先、回溯) -------------------------------------------------- 152.BFS(广度优先) -------------------------------------------------------- 16 四.数论: ----------------------------------------------------------------- 171.最大公约数,最小公倍数:---------------------------------------------- 172.欧几里德扩展:-------------------------------------------------------- 173.大数除法求余、快速幂取余:-------------------------------------------- 174.同余: --------------------------------------------------------------- 195.筛素数 --------------------------------------------------------------- 19 五.图论 ------------------------------------------------------------------- 201.并查集: ------------------------------------------------------------- 202.最小生成树:---------------------------------------------------------- 201) Prim算法------------------------------------------------------- 21 2)克鲁斯卡尔算法--------------------------------------------------- 223.最短路径: ------------------------------------------------------------ 231)最短路径dijkstra算法-------------------------------------------- 23 1)Floyd算法(最短路径)------------------------------------------- 284.最大匹配 ------------------------------------------------------------- 295.最大流 --------------------------------------------------------------- 31 六.数据结构 --------------------------------------------------------------- 331.RMQ ------------------------------------------------------------------ 332.树状数组 ------------------------------------------------------------- 351)一维树状数组------------------------------------------------------ 352)二维树状数组------------------------------------------------------ 37 七.各种处理函数 ----------------------------------------------------------- 381.字符串 --------------------------------------------------------------- 381)字符串分解函数strtok-------------------------------------------- 38 八.动态规划 --------------------------------------------------------------- 391.最长公共子序列-------------------------------------------------------- 392.单调递增(递减)最长子序列-------------------------------------------- 403.整数规划:------------------------------------------------------------ 42一.高精度计算:1.高精度加法:1)C++ string类实现:#include<string>void sum(string &a,string b) // a=a+b{ int i,j,k,c,s;while (a.length()>b.length()) b='0'+b;// a,b处理成一样长 while (b.length()>a.length()) a='0'+a;c=0;for (i=a.length()-1; i>=0; i--){ s=a[i]-48+b[i]-48+c;if ( s>9 ) { s=s%10; c=1;} else c=0;a[i]=48+s;}if ( c>0 ) a='1'+a;}2)字符数组char实现:#include<string.h>void add(char a[],char b[])//a=a+b{int i,j,k,sum=0;k=strlen(a)>strlen(b)?strlen(a):strlen(b);a[k+1]=0;for(i=strlen(a)-1,j=strlen(b)-1;i>=0||j>=0;i--,j--,k--){ if(i>=0) sum+=a[i]-'0'; if(j>=0) sum+=b[j]-'0';a[k]=sum%10+'0'; sum/=10;}if(sum) a[0]=sum+'0';else strcpy(a,&a[1]);}2.高精度减法:1)C++ string类实现:#include<string>void f(string &a,string b){int i,j,sum=0;for(i=a.length()-1,j=b.length()-1;i>=0||j>=0;i--,j--){sum+=a[i]-'0'; if(j>=0) sum-=b[j]-'0';if(sum<0) {a[i]=sum+10+'0';sum=-1;}else {a[i]=sum+'0';sum=0;}}if(a[0]=='0') a=&a[1];for(i=0;a[i]=='0'&&i<a.length();i++) ;if(i==a.length()) a="0";}2)字符数组char实现:#include <string.h>void jian(char a[],char b[])//a-=b{int i,j,sum=0;for(i=strlen(a)-1,j=strlen(b)-1;i>=0||j>=0;i--,j--){sum+=a[i]-'0'; if(j>=0) sum-=b[j]-'0';if(sum<0) {a[i]=sum+10+'0';sum=-1;}else {a[i]=sum+'0';sum=0;}}if(a[0]=='0') strcpy(a,&a[1]);for(i=0;a[i]=='0';i++) ;if(i==strlen(a)) strcpy(a,"0");}3.高精度乘法1)字符数组char实现:#include <string.h>void chen(char a[],char b[])//a=a*b{ int i,j,k,l,sum,c[410]={0};l=strlen(a)+strlen(b);for(i=strlen(b)-1;i>=0;i--)for(j=strlen(a)-1,k=i+j+1;j>=0;j--,k--){ sum=(b[i]-'0')*(a[j]-'0')+c[k];c[k]=sum%10;c[k-1]+=sum/10;}for(i=c[0]?0:1,j=0;i<l;i++)a[j++]=(c[i]+'0'); a[j]=0;}2)C++ string类实现:#include<string>void chenn(string &a,string b)//a=a*b{ int i,j,k,l,sum,c[410]={0};l=a.length()+b.length();for(i=b.length()-1;i>=0;i--)for(j=a.length()-1,k=i+j+1;j>=0;j--,k--){ sum=(b[i]-'0')*(a[j]-'0')+c[k];c[k]=sum%10;c[k-1]+=sum/10;}i=c[0]?0:1;while(a.length()<l-i) a=a+'0';for(j=0;i<l;i++)a[j++]=(c[i]+'0');}4.高精度阶乘(压缩五位)#include<iostream>#include<iomanip>using namespace std;int a[10000];int main(void){int i,n,w,up,j;while(cin>>n){for(w=a[0]=i=1;i<=n;i++){ for(j=0,up=0;j<w;j++){a[j]=i*a[j]+up;up=a[j]/100000;a[j]%=100000;}if(up) a[w++]=up;}cout<<a[w-1];for(i=w-2;i>=0;i--)cout<<setfill('0')<<setw(5)<<a[i]; cout<<endl;}}5.高精度小数加法#include<cstring>#include<algorithm>void quw0(char a[]) //去除尾部多余的零 eg: 3.5+3.5=7.0变成 7 { int i;for(i=0;i<strlen(a);i++) //判断有没有小数点if(a[i]=='.') break;if(i!=strlen(a)){i=strlen(a)-1;while(a[i]=='0') {a[i]=0;;i--;}if(a[i]=='.') a[i]=0;;}}void add(char *a,char *b)//a=a+b{int i=0,j=0,la=strlen(a),lb=strlen(b),sum=0;while((a[i]-'.')&&i<la) i++;while((b[j]-'.')&&j<lb) j++;if(i==la) {a[i]='.';la++;};if(j==lb) {b[j]='.';lb++;};while(la-i>lb-j) {b[lb]='0';lb++;}while(lb-j>la-i) {a[la]='0';la++;}if(la<lb) { swap(a,b); swap(la,lb); }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';else strcpy(a,&a[1]);quw0(a);//根据题目需要是否保留尾0}二.计算几何:1.线段相交:int xj(point x1,point x2,point x3,point x4)//相交为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) )return 0;//不交:矩形排斥实验,最小的>最大的肯定不交int a,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);return a*b<=0&&c*d<=0;}2.点关于直线的对称点:点:(a,b),直线:Ax+By+C=0#include <stdio.h>int main(){int n;float a,b,A,B,C,a1,b1;scanf("%d\n",&n);while(n--){ scanf("%f %f %f %f %f",&a,&b,&A,&B,&C);int a1=int (a-2*A*(A*a+B*b+C)/(A*A+B*B));int b1=int (b-2*B*(A*a+B*b+C)/(A*A+B*B));printf("%d %d\n",a1,b1);}}3.求凸包//根据题目改动数据类型,数组大小,排序方式#include <algorithm>#define eps 1e-8struct point{int x,y;};point pnt[100003],res[100005];bool operator<( point A,point B )//按y排也可,具体看题目要求{ return A.x < B.x || (A.x == B.x && A.y < B.y); }double mult(point p0,point p1,point p2){ r eturn (p1.x-p0.x)*(p2.y-p0.y)-(p1.y-p0.y)*(p2.x-p0.x); }//数组下标从0开始,n是点的个数,选中的点在保存在res数组中,个数是topint graham(point pnt[], int n, point res[])//选中的点在保存在res数组中,个数是top{ int i, len, k = 0, top = 1;sort(pnt, pnt + n); //用cmp可能超时,原因未知if (n == 0) return 0; res[0] = pnt[0];if (n == 1) return 1; res[1] = pnt[1];if (n == 2) return 2; res[2] = pnt[2];for (i = 2; i < n; 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];}return top; // 返回凸包中点的个数}4.多边形面积//点必须是顺时针给出或逆时针给出才可用此法//使用时注意数据类型,和数据大小struct point{int x,y;}a[105];int duo(point a[],int n) //点在数组 a[]中,个数是n{ int i,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;return s;// if(s%2) cout<<s/2<<".5"<<endl; 若为longl long 类型,不要用double// else cout<<s/2<<".0"<<endl;}5.皮克定理://S=a+b÷2-1//(其中a表示多边形内部的点数,b表示多边形边界上的点数,S表示多边形的面积)#include<cmath>struct point{int x,y;};int gcd(int m,int n){if(n==0) return m;return gcd(n,m%n);}int bian(point a[],int n)//算出点A和点B组成的线段上的点{ int s=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));return s;}int duo(point a[],int n)//求n边形的面积,注意ans未除2;{int i,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;return s;}6.三角形:1)点和三角形的关系//注意数据类型#include <cmath>struct point{int x,y;};bool operator ==(point A,point B){return A.x==B.x&&A.y==B.y;} int area(point A,point B,point C)//三角形面积,未除2{int s=abs((B.x-A.x)*(C.y-A.y)-(B.y-A.y)*(C.x-A.x));return s;}int pan3(point a[],point p) //若点在三角形内(不含边界),返回1;{int sa,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) return 1;if((!sa||!sb||!sc)&&s==sa+sb+sc){if(p==a[0]||p==a[1]||p==a[2]) return 4;//若点在三角形顶点上,返回4。
acm常用模板
ACM Fighting!ACM Fighting! (2)1.计算几何 (5)1.1 注意 (5)1.2几何公式 (6)1.3 多边形 (8)1.4多边形切割 (11)1.5 浮点函数 (12)1.6 面积 (18)1.7球面 (18)1.8三角形 (19)1.9三维几何 (22)1.10 凸包 (30)1.11 网格 (32)1.12 圆 (33)1.13 矢量运算求几何模板 (35)1.14结构体表示几何图形 (47)1.15四城部分几何模板 (52)1.16 一些代码 (54)1.16.1 最小圆覆盖_zju1450 (54)1.16.2 直线旋转_两凸包的最短距离(poj3608) (58)1.16.3 扇形的重心 (62)1.16.4 根据经度纬度求球面距离 (62)1.16.5 多边形的重心 (64)1.16.6 存不存在一个平面把两堆点分开(poj3643) (66)1.16.7 pku_3335_判断多边形的核是否存在 (67)1.16.8 pku_2600_二分+圆的参数方程 (74)1.16.9 pku_1151_矩形相交的面积 (76)1.16.10 pku_1118_共线最多的点的个数 (78)1.16.11 pku2826_线段围成的区域可储水量 (80)1.16.12 Pick公式 (84)1.16.13 N点中三个点组成三角形面积最大 (86)1.16.14 直线关于圆的反射 (89)1.16.15 pku2002_3432_N个点最多组成多少个正方形(hao) (94)1.16.16 pku1981_单位圆覆盖最多点(poj1981)CircleandPoints (97)1.16.17 pku3668_GameofLine_N个点最多确定多少互不平行的直线(poj3668) (99)1.16.18 求凸多边形直径 (100)2.组合 (102)2.1 组合公式 (102)2.2 排列组合生成 (102)2.3 生成gray码 (104)2.4 置换(polya) (104)2.5 字典序全排列 (105)2.6 字典序组合 (105)2.7 一些原理及其例子 (106)3.数论 (108)3.1 阶乘最后非0位 (108)3.2 模线性方程组 (108)3.3 素数 (110)3.4 欧拉函数 (114)3.6高精度 (116)3.6.1平方根 (116)3.6.2 高精度乘幂 (117)3.7 高斯消元回代法 (122)3.8 数值计算 (124)3.8.1 定积分计算 (124)3.8.2 多项式求根(牛顿法) (125)3.8.3 周期性方程(追赶法) (127)4.排序 (128)4.1快速选择算法 (128)4.2归并排序+逆序数的求取 (128)5.字符串 (130)5.1 KMP应用 (130)5.2 后缀数组 (131)5.3 中缀表达式转后缀表达式 (134)5.4 Firefighters 表达式求值 (135)6.博弈 (139)6.1 博弈的AB剪枝 (139)6.2 博弈SG函数局势分割 (141)7.数据结构 (142)7.1 TRIE (142)7.2 线段树 (147)7.3 并查集 (151)7.4 树状数组 (152)7.5 点树 (154)7.6 STL (156)7.7 离散化 (157)8.图论 (158)8.0 2-SAT (158)8.2 寻找Euler回路 (163)8.3 拓扑排序 (163)8.4 差分约束系统 (164)8.5 笛卡尔树 (165)8.6 LCA和RMQ (167)8.7 割和桥 (171)8.8 最小生成树(kruskal) (172)8.9 最短路径 (173)8.10 最大网络流 (175)8.11 最小费用流 (180)8.12 最大团问题 (182)8.13 二分图匹配 (184)8.14 带权的最优二分图匹配 (184)9.搜索算法概略 (187)9.1 迭代深搜+IDA* (187)9.2 分之界限法(深搜) (189)9.3 A* 8数码问题( pascal ) (192)9.4 优先队列广搜 (194)10.应用 (197)10.1 Joseph问题 (197)10.3 布尔母函数 (198)10.4 第k元素 (199)10.5 幻方构造 (199)10.6 模式匹配(kmp) (201)10.7 逆序对数 (201)10.8 字符串最小表示 (202)10.9 最长公共单调子序列 (202)10.10 最长子序列 (204)10.11 最大子串匹配 (204)10.12 最大子段和 (205)10.13 最大子阵和 (206)11.其它 (207)11.1 大数(只能处理正数) (207)11.2 分数 (212)11.3 矩阵 (214)11.4 线性方程组 (216)11. 5 线性相关 (218)11.6 日期 (219)11.7 读入 (220)11.8 函数 (220)1.计算几何1.1 注意1. 注意舍入方式(0.5的舍入方向);防止输出-0.2. 几何题注意多测试不对称数据.3. 整数几何注意xmult和dmult是否会出界;符点几何注意eps的使用.4. 避免使用斜率;注意除数是否会为0.5. 公式一定要化简后再代入.6. 判断同一个2*PI域内两角度差应该是abs(a1-a2)<beta||abs(a1-a2)>pi+pi-beta;相等应该是abs(a1-a2)<eps||abs(a1-a2)>pi+pi-eps;7. 需要的话尽量使用atan2,注意:atan2(0,0)=0,atan2(1,0)=pi/2,atan2(-1,0)=-pi/2,atan2(0,1)=0,atan2(0,-1)=pi.8. cross product = |u|*|v|*sin(a)dot product = |u|*|v|*cos(a)9. (P1-P0)x(P2-P0)结果的意义:正: <P0,P1>在<P0,P2>顺时针(0,pi)内负: <P0,P1>在<P0,P2>逆时针(0,pi)内0 : <P0,P1>,<P0,P2>共线,夹角为0或pi10. 误差限缺省使用1e-8!1.2几何公式三角形:1. 半周长P=(a+b+c)/22. 面积S=aHa/2=absin(C)/2=sqrt(P(P-a)(P-b)(P-c))3. 中线Ma=sqrt(2(b^2+c^2)-a^2)/2=sqrt(b^2+c^2+2bccos(A))/24. 角平分线Ta=sqrt(bc((b+c)^2-a^2))/(b+c)=2bccos(A/2)/(b+c)5. 高线Ha=bsin(C)=csin(B)=sqrt(b^2-((a^2+b^2-c^2)/(2a))^2)6. 内切圆半径r=S/P=asin(B/2)sin(C/2)/sin((B+C)/2)=4Rsin(A/2)sin(B/2)sin(C/2)=sqrt((P-a)(P-b)(P-c)/P)=Ptan(A/2)tan(B/2)tan(C/2)7. 外接圆半径R=abc/(4S)=a/(2sin(A))=b/(2sin(B))=c/(2sin(C))四边形:D1,D2为对角线,M对角线中点连线,A为对角线夹角1. a^2+b^2+c^2+d^2=D1^2+D2^2+4M^22. S=D1D2sin(A)/2(以下对圆的内接四边形)3. ac+bd=D1D24. S=sqrt((P-a)(P-b)(P-c)(P-d)),P为半周长正n边形:R为外接圆半径,r为内切圆半径1. 中心角A=2PI/n2. 内角C=(n-2)PI/n3. 边长a=2sqrt(R^2-r^2)=2Rsin(A/2)=2rtan(A/2)4. 面积S=nar/2=nr^2tan(A/2)=nR^2sin(A)/2=na^2/(4tan(A/2))圆:1. 弧长l=rA2. 弦长a=2sqrt(2hr-h^2)=2rsin(A/2)3. 弓形高h=r-sqrt(r^2-a^2/4)=r(1-cos(A/2))=atan(A/4)/24. 扇形面积S1=rl/2=r^2A/25. 弓形面积S2=(rl-a(r-h))/2=r^2(A-sin(A))/2棱柱:1. 体积V=Ah,A为底面积,h为高2. 侧面积S=lp,l为棱长,p为直截面周长3. 全面积T=S+2A棱锥:1. 体积V=Ah/3,A为底面积,h为高(以下对正棱锥)2. 侧面积S=lp/2,l为斜高,p为底面周长3. 全面积T=S+A棱台:1. 体积V=(A1+A2+sqrt(A1A2))h/3,A1.A2为上下底面积,h为高(以下为正棱台)2. 侧面积S=(p1+p2)l/2,p1.p2为上下底面周长,l为斜高3. 全面积T=S+A1+A2圆柱:1. 侧面积S=2PIrh2. 全面积T=2PIr(h+r)3. 体积V=PIr^2h圆锥:1. 母线l=sqrt(h^2+r^2)2. 侧面积S=PIrl3. 全面积T=PIr(l+r)4. 体积V=PIr^2h/3圆台:1. 母线l=sqrt(h^2+(r1-r2)^2)2. 侧面积S=PI(r1+r2)l3. 全面积T=PIr1(l+r1)+PIr2(l+r2)4. 体积V=PI(r1^2+r2^2+r1r2)h/3球:1. 全面积T=4PIr^22. 体积V=4PIr^3/3球台:1. 侧面积S=2PIrh2. 全面积T=PI(2rh+r1^2+r2^2)3. 体积V=PIh(3(r1^2+r2^2)+h^2)/6球扇形:1. 全面积T=PIr(2h+r0),h为球冠高,r0为球冠底面半径2. 体积V=2PIr^2h/31.3 多边形#include <stdlib.h>#include <math.h>#define MAXN 1000#define offset 10000#define eps 1e-8#define zero(x) (((x)>0?(x):-(x))<eps)#define _sign(x) ((x)>eps?1:((x)<-eps?2:0))struct point{double x,y;};struct line{point a,b;};double xmult(point p1,point p2,point p0){return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y); }//判定凸多边形,顶点按顺时针或逆时针给出,允许相邻边共线int is_convex(int n,point* p){int i,s[3]={1,1,1};for (i=0;i<n&&s[1]|s[2];i++)s[_sign(xmult(p[(i+1)%n],p[(i+2)%n],p[i]))]=0;return s[1]|s[2];}//判定凸多边形,顶点按顺时针或逆时针给出,不允许相邻边共线int is_convex_v2(int n,point* p){int i,s[3]={1,1,1};for (i=0;i<n&&s[0]&&s[1]|s[2];i++)s[_sign(xmult(p[(i+1)%n],p[(i+2)%n],p[i]))]=0;return s[0]&&s[1]|s[2];}//判点在凸多边形内或多边形边上,顶点按顺时针或逆时针给出int inside_convex(point q,int n,point* p){int i,s[3]={1,1,1};for (i=0;i<n&&s[1]|s[2];i++)s[_sign(xmult(p[(i+1)%n],q,p[i]))]=0;return s[1]|s[2];}//判点在凸多边形内,顶点按顺时针或逆时针给出,在多边形边上返回0int inside_convex_v2(point q,int n,point* p){int i,s[3]={1,1,1};for (i=0;i<n&&s[0]&&s[1]|s[2];i++)s[_sign(xmult(p[(i+1)%n],q,p[i]))]=0;return s[0]&&s[1]|s[2];}//判点在任意多边形内,顶点按顺时针或逆时针给出//on_edge表示点在多边形边上时的返回值,offset为多边形坐标上限int inside_polygon(point q,int n,point* p,int on_edge=1){point q2;int i=0,count;while (i<n)for (count=i=0,q2.x=rand()+offset,q2.y=rand()+offset;i<n;i++)if(zero(xmult(q,p[i],p[(i+1)%n]))&&(p[i].x-q.x)*(p[(i+1)%n].x-q.x)<eps&&(p[i].y-q.y)*(p[(i+1)%n].y-q.y)<eps) return on_edge;else if (zero(xmult(q,q2,p[i])))break;else if (xmult(q,p[i],q2)*xmult(q,p[(i+1)%n],q2)<-eps&&xmult(p[i],q,p[(i+1)%n])*xmult(p[i],q2,p[(i+1)%n])<-eps) count++;return count&1;}inline int opposite_side(point p1,point p2,point l1,point l2){return xmult(l1,p1,l2)*xmult(l1,p2,l2)<-eps;}inline int dot_online_in(point p,point l1,point l2){return zero(xmult(p,l1,l2))&&(l1.x-p.x)*(l2.x-p.x)<eps&&(l1.y-p.y)*(l2.y-p.y)<eps;}//判线段在任意多边形内,顶点按顺时针或逆时针给出,与边界相交返回1int inside_polygon(point l1,point l2,int n,point* p){point t[MAXN],tt;int i,j,k=0;if (!inside_polygon(l1,n,p)||!inside_polygon(l2,n,p))return 0;for (i=0;i<n;i++)if (opposite_side(l1,l2,p[i],p[(i+1)%n])&&opposite_side(p[i],p[(i+1)%n],l1,l2))return 0;else if (dot_online_in(l1,p[i],p[(i+1)%n]))t[k++]=l1;else if (dot_online_in(l2,p[i],p[(i+1)%n]))t[k++]=l2;else if (dot_online_in(p[i],l1,l2))t[k++]=p[i];for (i=0;i<k;i++)for (j=i+1;j<k;j++){tt.x=(t[i].x+t[j].x)/2;tt.y=(t[i].y+t[j].y)/2;if (!inside_polygon(tt,n,p))return 0;}return 1;}point intersection(line u,line v){point ret=u.a;double t=((u.a.x-v.a.x)*(v.a.y-v.b.y)-(u.a.y-v.a.y)*(v.a.x-v.b.x)) /((u.a.x-u.b.x)*(v.a.y-v.b.y)-(u.a.y-u.b.y)*(v.a.x-v.b.x));ret.x+=(u.b.x-u.a.x)*t;ret.y+=(u.b.y-u.a.y)*t;return ret;}point barycenter(point a,point b,point c){line u,v;u.a.x=(a.x+b.x)/2;u.a.y=(a.y+b.y)/2;u.b=c;v.a.x=(a.x+c.x)/2;v.a.y=(a.y+c.y)/2;v.b=b;return intersection(u,v);}//多边形重心point barycenter(int n,point* p){point ret,t;double t1=0,t2;int i;ret.x=ret.y=0;for (i=1;i<n-1;i++)if (fabs(t2=xmult(p[0],p[i],p[i+1]))>eps){t=barycenter(p[0],p[i],p[i+1]);ret.x+=t.x*t2;ret.y+=t.y*t2;t1+=t2;}if (fabs(t1)>eps)ret.x/=t1,ret.y/=t1;return ret;}1.4多边形切割//多边形切割//可用于半平面交#define MAXN 100#define eps 1e-8#define zero(x) (((x)>0?(x):-(x))<eps)struct point{double x,y;};double xmult(point p1,point p2,point p0){return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);}int same_side(point p1,point p2,point l1,point l2){return xmult(l1,p1,l2)*xmult(l1,p2,l2)>eps;}point intersection(point u1,point u2,point v1,point v2){ point ret=u1;double t=((u1.x-v1.x)*(v1.y-v2.y)-(u1.y-v1.y)*(v1.x-v2.x))/((u1.x-u2.x)*(v1.y-v2.y)-(u1.y-u2.y)*(v1.x-v2.x));ret.x+=(u2.x-u1.x)*t;ret.y+=(u2.y-u1.y)*t;return ret;}//将多边形沿l1,l2确定的直线切割在side侧切割,保证l1,l2,side不共线void polygon_cut(int& n,point* p,point l1,point l2,point side){ point pp[100];int m=0,i;for (i=0;i<n;i++){if (same_side(p[i],side,l1,l2))pp[m++]=p[i];if (!same_side(p[i],p[(i+1)%n],l1,l2)&&!(zero(xmult(p[i],l1,l2))&&zero(xmult(p[(i+1)%n],l1,l2)))) pp[m++]=intersection(p[i],p[(i+1)%n],l1,l2);}for (n=i=0;i<m;i++)if (!i||!zero(pp[i].x-pp[i-1].x)||!zero(pp[i].y-pp[i-1].y))p[n++]=pp[i];if (zero(p[n-1].x-p[0].x)&&zero(p[n-1].y-p[0].y))n--;if (n<3)n=0;}1.5 浮点函数//浮点几何函数库#include <math.h>#define eps 1e-8#define zero(x) (((x)>0?(x):-(x))<eps)struct point{double x,y;};struct line{point a,b;};//计算cross product (P1-P0)x(P2-P0)double xmult(point p1,point p2,point p0){return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);}double xmult(double x1,double y1,double x2,double y2,double x0,double y0){return (x1-x0)*(y2-y0)-(x2-x0)*(y1-y0);}//计算dot product (P1-P0).(P2-P0)double dmult(point p1,point p2,point p0){return (p1.x-p0.x)*(p2.x-p0.x)+(p1.y-p0.y)*(p2.y-p0.y);}double dmult(double x1,double y1,double x2,double y2,double x0,double y0){return (x1-x0)*(x2-x0)+(y1-y0)*(y2-y0);}//两点距离double distance(point p1,point p2){return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));}double distance(double x1,double y1,double x2,double y2){return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));}//判三点共线int dots_inline(point p1,point p2,point p3){return zero(xmult(p1,p2,p3));}int dots_inline(double x1,double y1,double x2,double y2,double x3,double y3){return zero(xmult(x1,y1,x2,y2,x3,y3));}//判点是否在线段上,包括端点int dot_online_in(point p,line l){return zero(xmult(p,l.a,l.b))&&(l.a.x-p.x)*(l.b.x-p.x)<eps&&(l.a.y-p.y)*(l.b.y-p.y)<eps;}int dot_online_in(point p,point l1,point l2){return zero(xmult(p,l1,l2))&&(l1.x-p.x)*(l2.x-p.x)<eps&&(l1.y-p.y)*(l2.y-p.y)<eps;}int dot_online_in(double x,double y,double x1,double y1,double x2,double y2){return zero(xmult(x,y,x1,y1,x2,y2))&&(x1-x)*(x2-x)<eps&&(y1-y)*(y2-y)<eps;}//判点是否在线段上,不包括端点int dot_online_ex(point p,line l){return dot_online_in(p,l)&&(!zero(p.x-l.a.x)||!zero(p.y-l.a.y))&&(!zero(p.x-l.b.x)||!zero(p.y-l.b.y)); }int dot_online_ex(point p,point l1,point l2){return dot_online_in(p,l1,l2)&&(!zero(p.x-l1.x)||!zero(p.y-l1.y))&&(!zero(p.x-l2.x)||!zero(p.y-l2.y)); }int dot_online_ex(double x,double y,double x1,double y1,double x2,double y2){return dot_online_in(x,y,x1,y1,x2,y2)&&(!zero(x-x1)||!zero(y-y1))&&(!zero(x-x2)||!zero(y-y2));}//判两点在线段同侧,点在线段上返回0int same_side(point p1,point p2,line l){return xmult(l.a,p1,l.b)*xmult(l.a,p2,l.b)>eps;}int same_side(point p1,point p2,point l1,point l2){return xmult(l1,p1,l2)*xmult(l1,p2,l2)>eps;}//判两点在线段异侧,点在线段上返回0int opposite_side(point p1,point p2,line l){return xmult(l.a,p1,l.b)*xmult(l.a,p2,l.b)<-eps;}int opposite_side(point p1,point p2,point l1,point l2){return xmult(l1,p1,l2)*xmult(l1,p2,l2)<-eps;}//判两直线平行int parallel(line u,line v){return zero((u.a.x-u.b.x)*(v.a.y-v.b.y)-(v.a.x-v.b.x)*(u.a.y-u.b.y));}int parallel(point u1,point u2,point v1,point v2){return zero((u1.x-u2.x)*(v1.y-v2.y)-(v1.x-v2.x)*(u1.y-u2.y));}//判两直线垂直int perpendicular(line u,line v){return zero((u.a.x-u.b.x)*(v.a.x-v.b.x)+(u.a.y-u.b.y)*(v.a.y-v.b.y));}int perpendicular(point u1,point u2,point v1,point v2){return zero((u1.x-u2.x)*(v1.x-v2.x)+(u1.y-u2.y)*(v1.y-v2.y));}//判两线段相交,包括端点和部分重合int intersect_in(line u,line v){if (!dots_inline(u.a,u.b,v.a)||!dots_inline(u.a,u.b,v.b))return !same_side(u.a,u.b,v)&&!same_side(v.a,v.b,u);return dot_online_in(u.a,v)||dot_online_in(u.b,v)||dot_online_in(v.a,u)||dot_online_in(v.b,u);}int intersect_in(point u1,point u2,point v1,point v2){if (!dots_inline(u1,u2,v1)||!dots_inline(u1,u2,v2))return !same_side(u1,u2,v1,v2)&&!same_side(v1,v2,u1,u2);returndot_online_in(u1,v1,v2)||dot_online_in(u2,v1,v2)||dot_online_in(v1,u1,u2)||dot_online_in(v2,u1,u2); }//判两线段相交,不包括端点和部分重合int intersect_ex(line u,line v){return opposite_side(u.a,u.b,v)&&opposite_side(v.a,v.b,u);}int intersect_ex(point u1,point u2,point v1,point v2){return opposite_side(u1,u2,v1,v2)&&opposite_side(v1,v2,u1,u2);}//计算两直线交点,注意事先判断直线是否平行!//线段交点请另外判线段相交(同时还是要判断是否平行!)point intersection(line u,line v){point ret=u.a;double t=((u.a.x-v.a.x)*(v.a.y-v.b.y)-(u.a.y-v.a.y)*(v.a.x-v.b.x))/((u.a.x-u.b.x)*(v.a.y-v.b.y)-(u.a.y-u.b.y)*(v.a.x-v.b.x));ret.x+=(u.b.x-u.a.x)*t;ret.y+=(u.b.y-u.a.y)*t;return ret;}point intersection(point u1,point u2,point v1,point v2){point ret=u1;double t=((u1.x-v1.x)*(v1.y-v2.y)-(u1.y-v1.y)*(v1.x-v2.x))/((u1.x-u2.x)*(v1.y-v2.y)-(u1.y-u2.y)*(v1.x-v2.x));ret.x+=(u2.x-u1.x)*t;ret.y+=(u2.y-u1.y)*t;return ret;}//点到直线上的最近点point ptoline(point p,line l){point t=p;t.x+=l.a.y-l.b.y,t.y+=l.b.x-l.a.x;return intersection(p,t,l.a,l.b);}point ptoline(point p,point l1,point l2){point t=p;t.x+=l1.y-l2.y,t.y+=l2.x-l1.x;return intersection(p,t,l1,l2);}//点到直线距离double disptoline(point p,line l){return fabs(xmult(p,l.a,l.b))/distance(l.a,l.b);}double disptoline(point p,point l1,point l2){return fabs(xmult(p,l1,l2))/distance(l1,l2);}double disptoline(double x,double y,double x1,double y1,double x2,double y2){ return fabs(xmult(x,y,x1,y1,x2,y2))/distance(x1,y1,x2,y2);}//点到线段上的最近点point ptoseg(point p,line l){point t=p;t.x+=l.a.y-l.b.y,t.y+=l.b.x-l.a.x;if (xmult(l.a,t,p)*xmult(l.b,t,p)>eps)return distance(p,l.a)<distance(p,l.b)?l.a:l.b;return intersection(p,t,l.a,l.b);}point ptoseg(point p,point l1,point l2){point t=p;t.x+=l1.y-l2.y,t.y+=l2.x-l1.x;if (xmult(l1,t,p)*xmult(l2,t,p)>eps)return distance(p,l1)<distance(p,l2)?l1:l2;return intersection(p,t,l1,l2);}//点到线段距离double disptoseg(point p,line l){point t=p;t.x+=l.a.y-l.b.y,t.y+=l.b.x-l.a.x;if (xmult(l.a,t,p)*xmult(l.b,t,p)>eps)return distance(p,l.a)<distance(p,l.b)?distance(p,l.a):distance(p,l.b);return fabs(xmult(p,l.a,l.b))/distance(l.a,l.b);}double disptoseg(point p,point l1,point l2){point t=p;t.x+=l1.y-l2.y,t.y+=l2.x-l1.x;if (xmult(l1,t,p)*xmult(l2,t,p)>eps)return distance(p,l1)<distance(p,l2)?distance(p,l1):distance(p,l2);return fabs(xmult(p,l1,l2))/distance(l1,l2);}//矢量V以P为顶点逆时针旋转angle并放大scale倍point rotate(point v,point p,double angle,double scale){point ret=p;v.x-=p.x,v.y-=p.y;p.x=scale*cos(angle);p.y=scale*sin(angle);ret.x+=v.x*p.x-v.y*p.y;ret.y+=v.x*p.y+v.y*p.x;return ret;}//p点关于直线L的对称点ponit symmetricalPointofLine(point p, line L){point p2;double d;d = L.a * L.a + L.b * L.b;p2.x = (L.b * L.b * p.x - L.a * L.a * p.x -2 * L.a * L.b * p.y - 2 * L.a * L.c) / d;p2.y = (L.a * L.a * p.y - L.b * L.b * p.y -2 * L.a * L.b * p.x - 2 * L.b * L.c) / d;return p2;}//求两点的平分线line bisector(point& a, point& b) {line ab, ans; ab.set(a, b);double midx = (a.x + b.x)/2.0, midy = (a.y + b.y)/2.0;ans.a = -ab.b, ans.b = -ab.a, ans.c = -ab.b * midx + ab.a * midy;return ans;}// 已知入射线、镜面,求反射线。
ACM动态规划问题简易模板(C++可编译)
1、0-1背包#include <stdio.h>#include <stdlib.h>//背包问题/*测试数据:输入:8 238 4 5 1 6 6 7 37 8 3 3 4 9 6 2输出:1 0 1 0 1 0 1 1*/int num,c;int v[10];int w[10];int m[10][30];//设m[i][j],则表示在前i个物品中,背包大小是j的情况下,背包所装东西的最大价值void knapsack(){int n=num-1;int jmax,i,j;if(w[n]<c) jmax=w[n];else jmax=c;for(i=0;i<jmax;i++)m[n][i]=0;for(i=w[n];i<=c;i++)m[n][i]=v[n];for(i=n-1;i>0;i--){if(w[i]<c) jmax=w[i];else jmax=c;for(j=0;j<jmax;j++)m[i][j]=m[i+1][j];for(j=w[i];j<=c;j++){if(m[i+1][j]<m[i+1][j-w[i]]+v[i])m[i][j]=m[i+1][j-w[i]]+v[i];elsem[i][j]=m[i+1][j];}}m[0][c]=m[1][c];if(c>=w[0]){if(m[0][c]<m[1][c-w[0]]+v[0])m[0][c]=m[1][c-w[0]]+v[0];}}void trackback(int *x){int n=num-1;int i;for(i=0;i<n;i++){if(m[i][c]==m[i+1][c]) x[i]=0;else{x[i]=1;c=c-w[i];}}if(m[n][c]>0) x[n]=1;else x[n]=0;}int main(){int i,x[10],j;scanf("%d %d",&num,&c);for(i=0;i<num;i++)scanf("%d",&v[i]);for(i=0;i<num;i++)scanf("%d",&w[i]);knapsack();for(i=0;i<=c;i++) printf("%3d",i);printf("\n");for(i=0;i<num;i++){for(j=0;j<=c;j++)printf("%3d",m[i][j]);printf("\n");}trackback(x);for(i=0;i<num;i++)printf("%d ",x[i]);printf("\n");return 0;}2、KMP算法#include<iostream>#include<string.h>using namespace std;inline void BuildNext(const char* pattern, size_t length, unsigned int* next){unsigned int i, t;i = 1;t = 0;next[1] = 0;while(i < length + 1){while(t > 0 && pattern[i - 1] != pattern[t - 1]){t = next[t];}++t;++i;if(pattern[i - 1] == pattern[t - 1]){next[i] = next[t];}else{next[i] = t;}}//pattern末尾的结束符控制,用于寻找目标字符串中的所有匹配结果用while(t > 0 && pattern[i - 1] != pattern[t - 1]){t = next[t];}++t;++i;next[i] = t;}unsigned int KMP(const char* text, size_t text_length, const char* pattern, size_t pattern_length, unsigned int* matches){unsigned int i, j, n;unsigned int next[pattern_length + 2];BuildNext(pattern, pattern_length, next);i = 0;j = 1;n = 0;while(pattern_length + 1 - j <= text_length - i){if(text[i] == pattern[j - 1]){++i;++j;//发现匹配结果,将匹配子串的位置,加入结果if(j == pattern_length + 1){matches[n++] = i - pattern_length;j = next[j];}}else{j = next[j];if(j == 0){++i;++j;}}//返回发现的匹配数return n;}int main(){char a[20],b[20];int n1,n2,n;unsigned int match[100];cin>>a;n1=strlen(a);//待匹配串cin>>b;n2=strlen(b);//模板串n=KMP(a,n1,b,n2,match);cout<<n<<endl;for(int i=0;i<n;i++)cout<<match[i]<<' ';}3、最大子段和#include<iostream>#include<stdio.h>using namespace std;int main(){int T,n;int a[50000];int hd[50000],tl[50000];scanf("%d",&T);while(T--){scanf("%d",&n);int i,temp,max;;for(i = 0;i < n;i++)scanf("%d",&a[i]);//hd[],left -> rightmax = hd[0] = a[0];for(i = 1;i < n;i++){temp = a[i] + hd[i - 1];hd[i] = temp > a[i] ? temp : a[i];}for(i = 1;i < n;i++){hd[i] = max > hd[i] ? max : hd[i];max = hd[i];//tl[],right -> leftmax = tl[n - 1] = a[n - 1];for(i = n - 2;i >= 0;i--){temp = a[i] + tl[i + 1];tl[i] = temp > a[i] ? temp : a[i];}for(i = n - 2;i >= 0;i--){tl[i] = max > tl[i] ? max : tl[i];max = tl[i];}max = hd[0] + tl[1];for(i = 1;i < n - 1;i++){temp = hd[i] + tl[i + 1];max = max > temp ? max : temp;}printf("%d\n",max);}return 0;}4、最长公共子序列(不严格连续)#include <stdio.h>#include <string.h>#define MAXLEN 100void LCSLength(char *x, char *y, int m, int n, int c[][MAXLEN], int b[][MAXLEN]) {int i, j;for(i = 0; i <= m; i++)c[i][0] = 0;for(j = 1; j <= n; j++)c[0][j] = 0;for(i = 1; i<= m; i++){for(j = 1; j <= n; j++){if(x[i-1] == y[j-1]){c[i][j] = c[i-1][j-1] + 1;b[i][j] = 0;}else if(c[i-1][j] >= c[i][j-1]){c[i][j] = c[i-1][j];b[i][j] = 1;}else{c[i][j] = c[i][j-1];b[i][j] = -1;}}}}void PrintLCS(int b[][MAXLEN], char *x, int i, int j) {if(i == 0 || j == 0)return;if(b[i][j] == 0){PrintLCS(b, x, i-1, j-1);printf("%c ", x[i-1]);}else if(b[i][j] == 1)PrintLCS(b, x, i-1, j);elsePrintLCS(b, x, i, j-1);}int main(int argc, char **argv){char x[MAXLEN] = {"ABCBDAB"};char y[MAXLEN] = {"BDCABA"};int b[MAXLEN][MAXLEN];int c[MAXLEN][MAXLEN];int m, n;m = strlen(x);n = strlen(y);LCSLength(x, y, m, n, c, b);PrintLCS(b, x, m, n);return 0;}5、最长公共子序列(不严格连续)#include<iostream>#include<cstdio>#include<memory.h>using namespace std;const int N = 505;int num1[N],num2[N],f[N][N];int main(){int t,n,m;scanf("%d",&t);while(t--){scanf("%d",&n);for(int i=1;i<=n;i++)scanf("%d",&num1[i]);scanf("%d",&m);for(int j=1;j<=m;j++)scanf("%d",&num2[j]);memset(f,0,sizeof(f));int answer=0;int ma;for(int i=1;i<=n;i++){ma=0;for(int j=1;j<=m;j++){f[i][j]=f[i-1][j];if(num1[i]>num2[j]&&f[i-1][j]>ma)ma=f[i-1][j];if(num1[i]==num2[j])f[i][j]=ma+1;}}for(int j=0;j<=m;j++)answer=max(answer,f[n][j]);printf("%d\n",answer);if(t!=0)printf("\n");}return 0;}6、最大子矩阵和#include <iostream>#include<memory.h>using namespace std;//求最大连续子矩阵和,动态规划,O(n^3) of time:/*输入41 -4 3 -8-3 5 2 -32 -1 8 1-1 1 -2 -4输出14*/int max_sum(int n, int *arr){ //求单个序列的最大连续子串和int result=0;int b=0;for(int i=0;i<n;i++){if(b>0) b+=arr[i];else b=arr[i];if(b>result) result=b;}return result;}int max_sum2(int m, int n, int **arr){int result=0;int *b=new int[n];for(int i=0;i<m;i++){memset(b,0,sizeof(int)*n);for(int j=i;j<m;j++){for(int k=0;k<n;k++)b[k]+=arr[j][k];//b[k]=arr[i][k]+arr[i+1][k]+...+arr[j][k]//从例子来说,当i=1,j=2时,有b[k]=arr[1][k]+arr[2][k],这时取到maxint max=max_sum(n,b);if(max>result) result=max;}}delete b;return result;}int main(){int N;cin>>N;int i,j;int **arr=new int*[N];for(i=0;i<N;i++){arr[i]=new int[N];for(j=0;j<N;j++)cin>>arr[i][j];}cout<<max_sum2(N,N,arr)<<endl;for(i=0;i<N;i++)delete arr[i];delete arr;return 0;}7、石子合并问题#include <iostream>#include <stdio.h>using namespace std;//石头合并问题PKU 1086 动态规划/*输入:44 1 2 3输出:*/#define MAX 1000000000int a[202];//每个石头的重量long f[202][202];//f[i][j],第i个石头分到第j个石头合并的最小代价long sum[202][202];//sum[i][j],第i个石头到第j个石头的重量之和void print(int num){int i,j;for(i=1;i<=num;i++){for(j=1;j<=num;j++)printf("%3d",f[i][j]);cout<<endl;}cout<<endl;}void cal(int num){int i,j,k,min,d;for(i=1;i<=num;i++)f[i][i]=0;//不合并时的代价for(i=1;i<num;i++){sum[i][i]=a[i];for(j=i+1;j<=num;j++){sum[i][j]=sum[i][j-1]+a[j];}}sum[num][num]=a[num];for(d=1;d<=num-1;d++){for(i=1;i<=num-d;i++){j=i+d;min=MAX;//i..k为一堆石头,k+1,k+2...j为另一堆石头//f[i][j]为f[i][k]+f[k+1][j]+sum[i][j]的最小值(i<=j<k)for(k=i;k<j;k++)if(min>f[i][k]+f[k+1][j]+sum[i][j]) min=f[i][k]+f[k+1][j]+sum[i][j];f[i][j]=min;print(num);}}}int main(){int num,i;scanf("%d",&num);for(i=1;i<=num;i++)cin>>a[i];cal(num);cout<<f[1][num]<<endl;return 0;}8、最大乘积#include <iostream>#include <stdio.h>#include <string.h>#include <stdlib.h>#include <math.h>using namespace std;//添加乘号得到最大乘积动态规划#define NMAX 12#define CMAX 7__int64 f[NMAX][CMAX];//f[i][j],长度为i,用了j个乘号后的最大值char str[22];void print(int num,int k){ //用于调试时打印f[][]int i,j;for(i=0;i<num;i++){for(j=1;j<=k;j++)printf("%6d",f[i][j]);cout<<endl;}cout<<endl;// system("pause");}int conv(int start,int num){ //在str[i]中,以start为起点,num为长度所表示的数字int sum,i;sum=0;for(i=1;i<=num;i++){sum*=10;sum+=str[start+i-1]-'0';}return sum;}void cal(int num,int chen){int i,j,temp,k;for(i=0;i<num;i++){ //初始化,不用乘号时的情况f[i][0]=conv(0,i+1);}for(j=1;j<=chen;j++){for(i=j;i<num;i++){temp=0;for(k=0;k<i;k++){//a1,a2,a3..an用j个乘号连接//看成是a1,a2...ak已经用j-1个乘号连接,//然后再与后面的ak+1,ak+2..an组成的数用1个乘号连接if(temp<f[k][j-1]*conv(k+1,i-k))temp=f[k][j-1]*conv(k+1,i-k);}f[i][j]=temp;//找到局部的最大乘积}// print(num,chen);}}int main(){int num,chen;//num为字符串长度while(scanf("%d%d",&num,&chen)!=EOF){scanf("%s",&str);cal(num,chen);printf("%I64d\n",f[num-1][chen]);}return 0;}。
ACM(五篇范例)
ACM(五篇范例)第一篇:ACMDijkstra 模板/*************************************** * About:有向图的Dijkstra算法实现 * Author:Tanky Woo * Blog:t=0;if(flag == 0){printf(“Non”);}else{for(int i=min;i<=max;++i){if(mark[i]==1 && arr[i]==0)cnt++;}}if(cnt==1)printf(“Yesn”);elseprintf(“Non”);}} return 0;搜索算法模板BFS:1.#include2.#include3.#include4.#includeing namespace std;6.const int maxn=100;7.bool vst[maxn][maxn];// 访问标记8.int dir[4][2]={0,1,0,-1,1,0,-1,0};// 方向向量9.10.struct State // BFS 队列中的状态数据结构 11.{ 12.int x,y;// 坐标位置13.int Step_Counter;// 搜索步数统计器14.};15.16.State a[maxn];17.18.boolCheckState(State s)// 约束条件检验19.{ 20.if(!vst[s.x][s.y] &&...)// 满足条件 1: 21.return 1;22.else // 约束条件冲突 23.return 0;24.} 25.26.void bfs(State st)27.{ 28.queue q;// BFS 队列29.State now,next;// 定义 2 个状态,当前和下一个30.st.Step_Counter=0;// 计数器清零 31.q.push(st);// 入队32.vst[st.x][st.y]=1;// 访问标记33.while(!q.empty())34.{ 35.now=q.front();// 取队首元素进行扩展36.if(now==G)// 出现目标态,此时为Step_Counter 的最小值,可以退出即可37.{ 38.......// 做相关处理39.return;40.} 41.for(int i=0;i<4;i++)42.{ 43.next.x=now.x+dir[i][0];// 按照规则生成下一个状态44.next.y=now.y+dir[i][1];45.next.Step_Counter=now.Step_Coun ter+1;// 计数器加1 46.if(CheckState(next))// 如果状态满足约束条件则入队 47.{ 48.q.push(next);49.vst[next.x][next.y]=1;//访问标记 50.} 51.} 52.q.pop();// 队首元素出队53.} 54.return;55.} 56.57.int main()58.{ 59.......60.return 0;61.}代码:胜利大逃亡Ignatius被魔王抓走了,有一天魔王出差去了,这可是Ignatius逃亡的好机会.魔王住在一个城堡里,城堡是一个A*B*C的立方体,可以被表示成A个B*C的矩阵,刚开始Ignatius被关在(0,0,0)的位置,离开城堡的门在(A-1,B-1,C-1)的位置,现在知道魔王将在T分钟后回到城堡,Ignatius每分钟能从一个坐标走到相邻的六个坐标中的其中一个.现在给你城堡的地图,请你计算出Ignatius能否在魔王回来前离开城堡(只要走到出口就算离开城堡,如果走到出口的时候魔王刚好回来也算逃亡成功),如果可以请输出需要多少分钟才能离开,如果不能则输出-1.Input 输入数据的第一行是一个正整数K,表明测试数据的数量.每组测试数据的第一行是四个正整数A,B,C和T(1<=A,B,C<=50,1<=T<=1000),它们分别代表城堡的大小和魔王回来的时间.然后是A块输入数据(先是第0块,然后是第1块,第2块......),每块输入数据有B行,每行有C个正整数,代表迷宫的布局,其中0代表路,1代表墙.(如果对输入描述不清楚,可以参考Sample Input中的迷宫描述,它表示的就是上图中的迷宫) 特别注意:本题的测试数据非常大,请使用scanf输入,我不能保证使用cin能不超时.在本OJ上请使用Visual C++提交.Output 对于每组测试数据,如果Ignatius能够在魔王回来前离开城堡,那么请输出他最少需要多少分钟,否则输出-1.Sample Input 1 3 3 4 20 0 1 1 1 0 0 1 1 0 1 1 1 1 1 1 1 1 0 0 1 0 1 1 1 0 0 0 0 0 1 1 0 0 1 1 0Sample Output 11代码:#include #include #include #include #includeusing namespace std;int tx[] = {0,1,-1,0,0,0,0};int ty[] = {0,0,0,1,-1,0,0};int tz[] = {0,0,0,0,0,1,-1};int arr[55][55][55];int known[55][55][55];// 访问标记int a,b,c,d;struct state{int x,y,z;// 所在的坐标int step_count;//统计搜索步数。
ACM题目分类(参考模板)
-----------------------------最优化问题-----------------------------------------------------------常规动态规划SOJ1162 I-KeyboardSOJ1685 ChopsticksSOJ1679 GangstersSOJ2096 Maximum SubmatrixSOJ2111 littleken bgSOJ2142 Cow ExhibitionSOJ2505 The County FairSOJ2818 QQ音速SOJ2469 Exploring PyramidsSOJ1833 Base NumbersSOJ2009 Zeros and OnesSOJ2032 The Lost HouseSOJ2113 数字游戏SOJ2289 A decorative fenceSOJ2494 ApplelandSOJ2440 The days in fzkSOJ2494 ApplelandSOJ2515 Ski LiftSOJ2718 BookshelfSOJ2722 Treats for the CowsSOJ2726 Deck of CardsSOJ2729 Space ElevatorSOJ2730 Lazy CowsSOJ2713 Cut the SequenceSOJ2768 BombSOJ2779 Find the max (I) (最大M子段和问题)SOJ2796 Letter DeletionSOJ2800 三角形SOJ2804 Longest Ordered Subsequence (II)SOJ2848 River Hopscotch(二分)SOJ2849 Cow Roller CoasterSOJ2886 Cow WalkSOJ2896 AlphacodeSOJ2939 bailey's troubleSOJ2994 RSISOJ3037 Painting the ballsSOJ3072 ComputersSOJ3078 windy's "K-Monotonic"SOJ3084 windy's cake IVSOJ3104 Game(注意大数运算,高精度)SOJ3110 k Cover of LineSOJ3111 k Median of LineSOJ3123 Telephone WireSOJ3142 Unfriendly Multi PermutationSOJ3213 PebblesSOJ3219 Cover UpSOJ3263 FunctionSOJ3264 Evil GameSOJ3339 graze2SOJ3341 SkiSOJ3352 The Baric BovineSOJ3503 Banana BoxesSOJ3633 Matches's GameSOJ3636 理想的正方形SOJ3711 Mountain RoadSOJ3723 Robotic Invasionnankai1134 Relation Orderingsrm150--div1--500----------------背包问题SOJ2222 Health PowerSOJ2749 The Fewest CoinsSOJ2785 Binary PartitionsSOJ2930 积木城堡SOJ3172 FishermanSOJ3300 Stockholm CoinsSOJ3360 Buying HaySOJ3531 Number Pyramids----------------状态DPSOJ2089 lykooSOJ2768 BombSOJ2819 AderSOJ2842 The TSP problemSOJ3025 Artillery(状态DP)SOJ3088 windy's cake VIIISOJ3183 Fgjlwj's boxesSOJ3259 Counting numbersSOJ3262 Square Fields(二分+状态DP) SOJ3371 Mixed Up CowsSOJ3631 Shopping Offers----------------树状DPSOJ 1870 Rebuilding RoadsSOJ 2136 Apple(树形依赖背包n*C算法) SOJ 2514 Milk Team SelectSOJ 2199 Apple TreeSOJ 3295 Treeland ExhibitionSOJ 3635 World Cup 2010hdoj1561 The more, The BetterPKU1655 Balancing ActPKU3107 GodfatherPKU3345 Bribing FIPAPKU2378 Tree CuttingPKU3140 Contestants DivisionPKU3659 Cell Phone Network---------------配合数据结构的优化DPSOJ 2702 AlannaSOJ 2978 TasksSOJ 3234 Finding SeatsSOJ 3540 股票交易-------------- 斜率优化SOJ 3710 特别行动队SOJ 3734 搬家SOJ 3736 Lawrence of Arabia---------------四边形不等式SOJ 1702 Cutting SticksSOJ 2775 Breaking Strings--------------- 最优化之排序(思考两个元素之间的先后关系,以此得出一个二元比较关系,并验证此关系可传递,反对称,进而排序)SOJ2509 The Milk QueueSOJ2547 cardsSOJ2850 Protecting the FlowersSOJ2957 Setting ProblemsSOJ3167 ComputerSOJ3331 Cards(2547加强版)SOJ3327 Dahema's Computer(通过此题学会排序)-----------------最优化之必要条件枚举(思考最优解所具有的性质,得出最优解的一个强必要条件,在此基础上枚举)SOJ3317 FGJ's PlaneSOJ3429 Food portion sizes--------------------------------贪心---------------------------------------SOJ1078 BlueEyes' ScheduleSOJ1203 Pass-MurailleSOJ1673 Gone FishingSOJ2574 pieSOJ2645 Buy One Get One FreeSOJ2701 In a CycleSOJ2876 Antimonotonicity(经典模型 O(n)算法)SOJ3343 Tower--------------------------------搜索---------------------------------------SOJ1106 DWeepSOJ1626 squareSOJ2061 8 puzzleSOJ2485 SudokuSOJ1045 SticksSOJ2736 FliptileSOJ2771 Collecting StonesSOJ2715 Maze BreakSOJ2518 Magic Cow ShoesSOJ2829 binary strings(双向BFS)SOJ3005 Dropping the stonesSOJ3136 scu07t01的迷宫(BFS预处理然后枚举交汇点)SOJ3330 Windy's Matrix(BFS)--------------------------------DFA-------------------------------------------------------状态矩阵SOJ1826 Number SequenceSOJ1936 FirepersonsSOJ2552 Number of TilingsSOJ2919 Matrix Power Series (学习矩阵的快速乘法从此开始)SOJ2920 Magic BeanSOJ3021 Quad TilingSOJ3046 Odd Loving BakersSOJ3176 E-stringSOJ3246 Tiling a Grid With DominoesSOJ3323 K-Satisfied NumbersSOJ3337 Wqb's Word----------------DFA+DPSOJ1112 Repeatless Numbers(DFA+二分)SOJ2913 Number SubstringSOJ2826 Apocalypse SomedaySOJ3128 windy和水星 -- 水星数学家 1SOJ3182 Windy numbers---------------------------------图论-----------------------------------------------------------最短路SOJ1697 Cashier EmploymentSOJ2325 Word TransformationSOJ2427 Daizi's path systemSOJ2468 CatcusSOJ2751 Wormholes(SPFA判断负圈回路的存在性)SOJ2932 道路SOJ3160 Clear And Present DangerSOJ3335 Windy's Route(最短路径的分层图思想)SOJ3346 Best Spot(N^3放心的写)SOJ3423 Revamping Trails---------------------查分约束SOJ1687 Intervals---------------------最小生成树SOJ1169 NetworkingSOJ2198 HighwaysSOJ3366 Watering HoleSOJ3427 Dark roads---------------------强连通分支SOJ2832 Mars city---------------------2-SATSOJ3535 Colorful DecorationHDU3062 Party---------------------拓扑排序SOJ1075 BlueEyes and Apples (II)---------------------无向连通图上的割点和割边问题SOJ1935 ElectricityWHU145 Railway---------------------二分图的匹配------------------最大匹配SOJ1183 Girls and BoysSOJ1186 CoursesSOJ2035 The Tiling ProblemSOJ2077 Machine ScheduleSOJ2160 Optimal MilkingSOJ2342 Rectangles(Beloved Sons 模型)SOJ2472 Guardian of DecencySOJ2681 平方数 2SOJ2737 AsteroidsSOJ2764 Link-up GameSOJ2806 LED DisplaySOJ2958 Weird FenceSOJ3043 Minimum CostSOJ3038 Beloved Sons(简单贪心一下)SOJ3453 Stock ChartsZOJ3265 Strange Game---------------最佳匹配SOJ1981 Going HomeWHU1451 Special Fish---------------------最近公共祖先问题SOJ1187 Closest Common AncestorsSOJ1677 How far awaySOJ3023 NetworkSOJ3098 Bond---------------------其他SOJ3013 treeSOJ3056 Average distance(树上的DFS)---------------------------------网络流----------------------------------------------------------最大流POJ 1273 Drainage DitchesPOJ 1274 The Perfect Stall (二分图匹配)POJ 1698 Alice's ChancePOJ 1459 Power NetworkPOJ 2112 Optimal Milking (二分)POJ 2455 Secret Milking Machine (二分)POJ 3189 Steady Cow Assignment (枚举)POJ 1637 Sightseeing tour (混合图欧拉回路)POJ 3498 March of the Penguins (枚举汇点)POJ 1087 A Plug for UNIXPOJ 1149 Pigs (构图题)ZOJ 2760 How Many Shortest Path (边不相交最短路的条数)POJ 2391 Ombrophobic Bovines (必须拆点,否则有BUG)WHU 1124 Football Coach (构图题)SGU 326 Perspective (构图题,类似于 WHU 1124)UVa 563 CrimewaveUVa 820 Internet BandwidthPOJ 3281 Dining (构图题)POJ 3436 ACM Computer FactoryPOJ 2289 Jamie's Contact Groups (二分)SGU 438 The Glorious Karlutka River =) (按时间拆点)SGU 242 Student's Morning (输出一组解)SGU 185 Two shortest (Dijkstra 预处理,两次增广,必须用邻接阵实现,否则 MLE) HOJ 2816 Power LinePOJ 2699 The Maximum Number of Strong Kings (枚举+构图)ZOJ 2332 GemsJOJ 2453 Candy (构图题)SOJ 2414 Leapin' LizardsSOJ 2835 Pick Up PointsSOJ 3312 Stockholm KnightsSOJ 3353 Total Flow--------------------最小割SOJ2662 PlaygroundSOJ3106 Dual Core CPUSOJ3109 Space flightSOJ3107 SelectSOJ3185 Black and whiteSOJ3254 Rain and FgjSOJ3134 windy和水星 -- 水星交通HOJ 2634 How to earn moreZOJ 2071 Technology Trader (找割边)HNU 10940 CoconutsZOJ 2532 Internship (找关键割边)POJ 1815 Friendship (字典序最小的点割集)POJ 3204 Ikki's Story I - Road Reconstruction (找关键割边)POJ 3308 ParatroopersPOJ 3084 Panic RoomPOJ 3469 Dual Core CPUZOJ 2587 Unique Attack (最小割的唯一性判定)POJ 2125 Destroying The Graph (找割边)ZOJ 2539 Energy MinimizationZOJ 2930 The Worst ScheduleTJU 2944 Mussy Paper (最大权闭合子图)POJ 1966 Cable TV Network (无向图点连通度)HDU 1565 方格取数(1) (最大点权独立集)HDU 1569 方格取数(2) (最大点权独立集)HDU 3046 Pleasant sheep and big big wolfPOJ 2987 Firing (最大权闭合子图)SPOJ 839 Optimal Marks (将异或操作转化为对每一位求最小割)HOJ 2811 Earthquake Damage (最小点割集)2008 Beijing Regional Contest Problem A Destroying the bus stations ( BFS 预处理 )(http://acmicpc-live-archive.uva.es/nuevoportal/data/problem.php?p=4322) ZOJ 2676 Network Wars (参数搜索)POJ 3155 Hard Life (参数搜索)ZOJ 3241 Being a Hero-----------------有上下界ZOJ 2314 Reactor Cooling (无源汇可行流)POJ 2396 Budget (有源汇可行流)SGU 176 Flow Construction (有源汇最小流)ZOJ 3229 Shoot the Bullet (有源汇最大流)HDU 3157 Crazy Circuits (有源汇最小流)-----------------最小费用流HOJ 2715 Matrix3HOJ 2739 The Chinese Postman ProblemPOJ 2175 Evacuation Plan (消一次负圈)POJ 3422 Kaka's Matrix Travels (与 Matrix3 类似)POJ 2516 Minimum Cost (按物品种类多次建图)POJ 2195 Going HomePOJ 3762 The Bonus Salary!BUAA 1032 Destroying a PaintingPOJ 2400 Supervisor, Supervisee (输出所有最小权匹配)POJ 3680 IntervalsHOJ 2543 Stone IVPOJ 2135 Farm TourSOJ 3186 SegmentsSOJ 2927 终极情报网SOJ 3634 星际竞速HDU 3376 Matrix Again-----------------------------------数据结构--------------------------------------------------------------------基础数据结构----------------------栈SOJ2511 MooooSOJ3085 windy's cake V(经典栈与单调性的结合)SOJ3279 hm 与 zx 的故事系列2SOJ3329 Maximum Submatrix II(转化为上面两题的模型)---------------------双端队列SOJ2978 TasksSOJ3139 Sliding Window(双端队列最经典的应用)SOJ3636 理想的正方形-------------------- --------------高级数据结构---------------------线段树SOJ1862 Choice PearsSOJ2057 The manager's worrySOJ2249 Mayor's postersSOJ2309 In the Army NowSOJ2436 Picture puzzle gameSOJ2556 Find the PermutationSOJ2562 The End of CorruptionSOJ2719 Corral the Cows(线段树+二分)SOJ2740 Balanced LineupSOJ2745 零序列SOJ2776 Matrix SearchingSOJ2808 Thermal Death of the UniverseSOJ2822 Buy TicketsSOJ2937 TetrisSOJ2938 Apple Tree(先DFS获得欧拉序列)SOJ2965 capitally playersSOJ2968 Matrix(二维线段树)SOJ3019 Count ColorSOJ3022 Difference Is Beautiful( RMQ+二分经典模型)SOJ3086 windy's cake VI(二维线段树)SOJ3099 A Simple Problem with IntegersSOJ3248 MousetrapSOJ3321 Windy's Sequence IISOJ3370 Light SwitchingSOJ3640 Special Subsequence---------------------树状数组SOJ2309 In the Army Now---------------------归并排序思想SOJ2906 Ultra-QuickSortSOJ2431 Cows distribute food(利用归并排序求逆序数:nlogn) SOJ2497 Number sequenceSOJ2559 What is the Rank?SOJ2728 MooFestSOJ3009 Stones for AmySOJ3010 K-th NumberSOJ3147 K-th number---------------------并查集SOJ1824 The SuspectsSOJ1953 keySOJ2245 Ubiquitous ReligionsSOJ2389 Journey to TibetSOJ2438 PetSOJ2490 Math teacher's testPOJ2832 How many pairs?POJ2821 Auto-Calculation MachineSOJ2979 食物链SOJ3282 Kingdom of HeavenSOJ3417 Skyscrapers------------------------块状链表SOJ3032 Big StringSOJ3035 反转序列----------------------------------- 字符串---------------------后缀数组SOJ1948 sekretarkaSOJ3045 Long Long MessageSOJ3075 回文子串SOJ3296 Windy's S---------------------KMPSOJ2652 OulipoSOJ2307 String MatchingSOJ3014 Seek the Name, Seek the FameSOJ3596 Article Decryption--------------------trie树SOJ3076 相同字符串SOJ3336 DiarySOJ3596 Article Decryption---------------------------------组合数学及数论-----------------------------SOJ1839 Relatives(Euler函数)SOJ1942 FotoSOJ2714 Mountains (II)SOJ2668 C(n,k)SOJ2666 分解 n!SOJ2106 GCD & LCM InverseSOJ2498 Count primeSOJ2238 Let it Bead(置换群-polya定理的应用)SOJ2924 完美交换(置换群)SOJ2638 Cow Sorting(置换群)-------------费马小定理SOJ 3578 H1N1's Problem--------------------------容斥原理SOJ3191 Free squareSOJ3082 windy's cake IISOJ3502 The Almost Lucky NumbersSOJ3547 Coprime----------------------------------博弈论------------------------------------SOJ1128 控制棋SOJ1866 Games(诡异的博弈)SOJ2197 A Funny GameSOJ2188 A multiplication gameSOJ2403 Black and white chessSOJ2477 Simple GameSOJ2687 草稿纸 2SOJ2688 草稿纸 3SOJ2836 Pick Up Points IISOJ2845 JangeSOJ2922 A New Tetris GameSOJ2993 NimSOJ3066 JohnSOJ3132 windy和水星 -- 水星游戏 1SOJ3133 windy和水星 -- 水星游戏 2SOJ3174 Good gameSOJ3307 Stockholm GameSOJ3446 Nim or not NimSOJ3461 Nim-kSOJ3463 Ordered NimSOJ3468 Flip CoinsSOJ3548 game如不慎侵犯了你的权益,请联系告知!SOJ3584 Baihacker and Oml-----------------------------------计算几何---------------------------------SOJ1138 WallSOJ1102 Picnic(本资料素材和资料部分来自网络,仅供参考。
ACM比赛模板
ACM比赛模板目录1.最小生成树 (4)2.最短路算法 (9)3.素数打表 (17)4.最大匹配 (18)5.线段树(敌兵布阵) (23)6.线段树(逆序树) (26)7.树形dp (29)8.树状数组(段跟新) (33)9.Kmp模板 (37)10.线段树(点跟新) (46)11.强连通 (50)12.最小割 (55)13.单源最短路(spfa) (62)14.三分查找 (66)15.字典树(统计难题) (68)16.最大流入门题1273 (72)17.状态压缩 (75)18.匈牙利(HDU 2063)(最大匹配) (77)19.凸包(HDU1348) (79)20.树状数组(HDU1166) (82)21.强连通 (84)22.前向星 (87)23.矩阵 (92)24.并查集 (94)25. SORT (95)26. STL (97)27. LCA (HDU 2874) (101)28. 01背包 (104)29. 状态压缩代码: (107)30. 快速幂 (111)31.矩阵快速幂 (113)32.GCD & LCM (116)11834. /** 大数(高精度)求幂**/12335. /** 大数除法与求余**/ (127)36. /** 大数阶乘**/ (131)37. /** 大数乘法**/ (133)38. /** 大数累加**/ (136)1.最小生成树要连通n个城市需要n-1条边线路。
可以把边上的权值解释为线路的造价。
则最小生成树表示使其造价最小的生成树。
prim算法(矩阵形式):#define inf 0x3f3f3f3fint prim(int n,int sta)//n表示有n个顶点,sta表从sta这个顶点出发生成最小生成树{int mark[M],dis[M];int i,sum = 0; //sum是总的最小生成树边权值for (i = 0;i < n;i ++) //初始化dis[i] 表从顶点sta到点i的权值 {dis[i] = mat[sta][i];mark[i] = 0;}mark[sta] = 1; //sta 这个顶点加入最小生成树中 for (i = 1;i < n;i ++) //循环n-1次,每次找出一条最小权值的边 n个点的图{ //只有n-1条边int min = inf; //inf 表无穷大for (j = 0;j < n;j ++)//找出当前未在最小生成树中边权最小的顶点if (!mark[j] && dis[j] < min)min = dis[j],flag = j;mark[flag] = 1; //把该顶点加入最小生成树中sum += dis[flag]; //sum加上其边权值for (j = 0;j < n;j ++) //以falg为起点更新到各点是最小权值if (dis[j] > mat[flag][j])dis[j] = mat[flag][j];}return sum; //返回边权总和}prim算法(边表形式):struct Edge//frm为起点,to为终点,w为边权,nxt指向下一个顶点{// int frm;int to,w,nxt;}edge[M];int vis[M],head[M],dis[M];void addedge (int cu,int cv,int cw)//生成边的函数{//edge[e].frm = cu;edge[e].to = cv;edge[e].w = cw;edge[e].nxt = head[cu];head[cu] = e ++;//edge[e].frm = cv;edge[e].to = cu;edge[e].w = cw;edge[e].nxt = head[cv];head[cv] = e ++;}int prim(int n,int sta) //n为顶点数量,sta为起点{int sum = 0;memset(dis,0x3f,sizeof(dis));memset(vis,0,sizeof(vis));for (i = head[sta];i != -1;i = edge[i].nxt)//遍历与sta点相连的所有顶点 {int v = edge[i].to;dis[v] = edge[i].w;}vis[sta] = 1; //加入到最小生成树中int m = n - 1; //只生成n-1条边,所以循环n-1次while (m --){int min = inf;for (i = 0;i < n;i ++)//找出当前边权最小的边if (!vis[i]&&dis[i] < min)flag = i,min = dis[i];sum += dis[flag];vis[flag] = 1;//加入到最小生成树中for (i = head[flag];i != -1;i = edge[i].nxt) //更新与flag顶点相连的点的dis{int v = edge[i].to;if (edge[i].w < dis[v])dis[v] = edge[i].w;}}return sum; //返回边权总和}int main (){e = 0; //记得初始化memset (head,-1,sizeof(head));scanf ("%d %d %d",&a,&b,&w);addedge(a,b,w);..........prim(n,sta);return 0;}Kruskal算法:struct Edge{int v1,v2,w;}edge[M],tree[M]; //w为v1顶点到v2顶点的边权/ *int Find (int parent[],int u)//第1种写法{int tmp = u;while (paren[tmp] != -1)tmp = parent[tmp];return tmp;}*/int Find (int u) //第2种写法{if (u != parent[u])parent[u] = Find(paren[u]);return parent[u];}bool cmp (Edge a,Edge b){return a.w < b.w;}int Kruskal()//parent[]表示集合{int parent[M];int i,j,sum,vf1,vf2;sort(edge,edge+E,cmp);// memset (parent,-1,sizeof(parent));//对应第1种并查集的初始化for (i = 0;i < n;i ++) //对应第2种并查集的初始化parent[i] = i;sum = i = j = 0;while (i < E && j < N - 1)//生成的边数为N-1{vf1 = Find(parent,edge[i].v1); //找这两个点的祖先vf2 = Find(parent,edge[i].v2);if (vf1 != vf2) //若两个点的祖先不同,说明不在同一集合{parent[vf2] = vf1;//把vf2点加到vf1点的集合中tree[j++] = edge[i];//把边加到tree[]数组中,这句题目没要求可忽略之sum += edge[i].w; //sum 加上其边权}i ++;}return sum;}最小生成树 -- Kruskal算法:运用数组存点与边的权值#include <stdio.h>#include <stdlib.h>#include <algorithm>#define N 150using namespace std;int m,n,u[N],v[N],w[N],p[N],r[N];int cmp(const int i,const int j) {return w[i]<w[j];} int find(int x) {return p[x]==x?x:p[x]=find(p[x]);}int kruskal(){int cou=0,x,y,i,ans=0;for(i=0;i<n;i++) p[i]=i;for(i=0;i<m;i++) r[i]=i;sort(r,r+m,cmp);for(i=0;i<m;i++){int e=r[i];x=find(u[e]);y=find(v[e]);if(x!=y) {ans += w[e];p[x]=y;cou++;}}if(cou<n-1) ans=0;return ans;}int main(){int i,ans;while(scanf("%d%d",&m,&n)!=EOF&&m){for(i=0;i<m;i++){scanf("%d%d%d",&u[i],&v[i],&w[i]);}ans=kruskal();if(ans) printf("%d\n",ans);else printf("?\n",ans);}return 0;}2.最短路算法①DIJKC++代码1.#define inf 0x3fffffff2.#define M 1053.4.int dist[M], map[M][M], n;5.bool mark[M];6.7.void init ()8.{9. int i, j;10. for (i = 1; i <= n; i++) //i==j的时候也可以初始化为0,只是有时候不合适11. for (j = 1; j <= n; j++)12. map[i][j] = inf;13.}14.15.void dijk (int u)16.{17. int i, j, mins, v;18. for (i = 1; i <= n; i++)19. {20. dist[i] = map[u][i];21. mark[i] = false;22. }23. mark[u] = true;24. dist[u] = 0; //既然上面的map当i==j时不是0,就要这句25. while (1)26. {27. mins = inf;28. for (j = 1; j <= n; j++)29. if (!mark[j] && dist[j] < mins)30. mins = dist[j], v = j;31. if (mins == inf)32. break;33. mark[v] = true;34. for (j = 1; j <= n; j++)35. if (!mark[j] && dist[v] + map[v][j] < dist[j])36. dist[j] = dist[v] + map[v][j];37. }38.}②Floyd1.#define inf 0x3fffffff //注意,太大会溢出2.#define M //最大点数3.int n, dist[M][M]; //n:实际点数4.5.void init () //有时候需要初始化6.{7. int i, j;8. for (i = 1; i <= n; i++)9. for (j = i + 1; j <= n; j++)10. dist[i][j] = dist[j][i] = inf;11.}12.13.void floyd ()14.{15. int i, j, k;16. for (k = 1; k <= n; k++)17. for (i = 1; i <= n; i++)18. for (j = 1; j <= n; j++) //有的题目会溢出就要自己变通了19. if (dist[i][k] + dist[k][j] < dist[i][j])20. dist[i][j] = dist[i][k] + dist[k][j];21.}③vector后插的SPFAC++代码1.#define inf 0x3fffffff2.#define M 105 //最大点数3.struct son{4. int v, w;5.};6.vector<son> g[M];7.bool inq[M]; //入队列标记8.int dist[M], n; //n:实际点数9.10.void init ()11.{12. for (int i = 1; i <= n; i++)13. g[i].clear();14.}15.16.void spfa (int u)17.{18. int i, v, w;19. for (i = 1; i <= n; i++)20. {21. dist[i] = inf;22. inq[i] = false;23. }24. queue<int> q;25. q.push (u);26. inq[u] = true;27. dist[u] = 0;28. while (!q.empty())29. {30. u = q.front();31. q.pop();32. inq[u] = false;33. for (i = 0; i < g[u].size(); i++)34. {35. v = g[u][i].v;36. w = g[u][i].w;37. if (dist[u] + w < dist[v])38. {39. dist[v] = dist[u] + w;40. if (!inq[v])41. {42. q.push (v);43. inq[v] = true;44. }45. }46. }47. }48.}④模拟前插的SPFA(多数情况下比③快,数据较为复杂就会看出来) C++代码1.#define inf 0x3fffffff2.#define M 1005 //最大点数3.4.struct edge{5. int v, w, next;6.}e[10005]; //估计好有多少条边7.8.int pre[M], cnt, dist[M], n;9.bool inq[M];10.//注意初始化11.void init ()12.{13. cnt = 0;14. memset (pre, -1, sizeof(pre));15.}16.//注意双向加边17.void addedge (int u, int v, int w) //加边函数,慢慢模拟就会明白的18.{19. e[cnt].v = v;20. e[cnt].w = w;21. e[cnt].next = pre[u]; //接替已有边22. pre[u] = cnt++; //自己前插成为u 派生的第一条边23.}24.25.void spfa (int u)26.{27. int v, w, i;28. for (i = 1; i <= n; i++) //对于从1到n的编号29. dist[i] = inf, inq[i] = false;30. dist[u] = 0;31. queue<int> q;32. q.push (u);33. inq[u] = true;34. while (!q.empty())35. {36. u = q.front();37. q.pop();38. inq[u] = false;39. for (i = pre[u]; i != -1; i = e[i].next)40. {41. w = e[i].w;42. v = e[i].v;43. if (dist[u] + w < dist[v])44. {45. dist[v] = dist[u] + w;46. if (!inq[v])47. {48. q.push (v);49. inq[v] = true;50. }51. }52. }53. }54.}3.素数打表#include<iostream>#include<cstring>#include<cmath>#define MAXN 5000using namespace std;int prime[MAXN];void print_prime(){int n = (int) sqrt(MAXN); for(int i = 2; i < n; i++) {if( !prime[i] ){for(int j = i*i; j < MAXN; j += i)prime[j] = 1;prime[++prime[0]] = i;}}for(int i = n; i < MAXN; i++)if(!prime[i])prime[++prime[0]] = i;}int main(){FILE *out;out = fopen("out.txt","w");print_prime();for(int i = 1; i <= prime[0]; i++)fprintf(out, "%d,", prime[i]); return 0;}4.最大匹配#include<stdio.h>#include<string.h>#define MAX 505bool used[MAX];bool match[MAX][MAX];int boys[MAX],girls[MAX];int k, n;void init(){memset(girls, -1, sizeof(girls));memset(boys, -1, sizeof(boys));memset(match, false, sizeof(match)); }bool can(int t){int i;for(i = 0; i < n; i ++){if(!used[i] && match[t][i]){u sed[i] = true;if(girls[i] = = -1 || can(girls[i])) {boys[t] = i;girls[i] = t;return true;}}}return false;}int main(){int tmpa, tmpb, i, res, t;while(scanf("%d", &n) != EOF){init();for(i = 0; i < n; ++i){scanf("%d: (%d)", &tmpa, &k);while(k- -){scanf("%d", &tmpb);match[tmpa][tmpb] = true;res = 0;for(i = 0; i < n; i++){if(boys[i] == -1){memset(used, false, sizeof(used));if(can(i)) res ++;}}}}printf("%d\n", n - res/2);}return 0;}5.线段树(敌兵布阵)#include<stdio.h>#include<string.h>int a[50005],n;void update(int x,int c){int i;for(i=x;i<=n;i+=(i&(-i)))a[i]+=c;}int s(int x){int i;int sum=0;for(i=x;i>0;i-=(i&-i)){sum+=a[i];} return sum;}int main(){int t,i,c,b=1;int z,y;char sh[15];scanf("%d",&t);while(t--){memset(a,0,sizeof(a));scanf("%d",&n);for(i=1;i<=n;i++){scanf("%d",&c);update(i,c);}printf("Case %d:\n",b++); while(~scanf("%s",sh)){if(sh[0]=='E')break;scanf("%d%d",&z,&y);if(sh[0]=='A')update(z,y);else if(sh[0]=='S')update(z,-y);else printf("%d\n",s(y)-s(z-1));}}return 0;}6.线段树(逆序树)#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;int a[500005],n;int b[500005];int d[500005];void update(int x,int c){ int i;for(i=x;i<=n;i+=(i&(-i))) a[i]+=c;}int s(int x){int i;int sum=0;for(i=x;i>0;i-=(i&-i)){sum+=a[i];}return sum;}int main(){int i,j;int ans;while(scanf("%d",&n)!=EOF,n) {memset(d,0,sizeof(d));for(i=1;i<=n;i++){scanf("%d",&b[i]);b[i]=b[i]+1;d[i]=b[i];}sort(b+1,b+n+1);memset(a,0,sizeof(a));ans=0;for(i=1;i<=n;i++){update(d[i],1);printf("%d ",s(d[i]));ans+=i-s(d[i]);printf("%d ",ans);}printf("%d\n",ans);}return 0;}7.树形dp#include<stdio.h>#include<iostream>using namespace std;struct Tree{intfather,child,brother,with_max,without_max ;int MAX(){returnwith_max>=without_max?with_max:without_ma x;}void init(){father=child=brother=without_max=0;}}tree[6001];void dfs(int id)int child;child=tree[id].child;while(child){dfs(child);tree[id].with_max+=tree[child].without_ max;tree[id].without_max+=tree[child].MAX() ;child=tree[child].brother;}}int main(){int n,i;while(scanf("%d",&n)!=EOF){for(i=1;i<=n;i++){scanf("%d",&tree[i].with_max);tree[i].init();}int a,b;while(scanf("%d%d",&a,&b),a||b){tree[a].father=b;tree[a].brother=tree[b].child;tree[b].child=a;}for(i=1;i<n;i++)if(!tree[i].father){dfs(i);printf("%d\n",tree[i].MAX());break;}}return 0;}8.树状数组(段跟新)1.#include <stdio.h>2.#include <string.h>3.const int MAXN=110000;4.int n,c[MAXN];5.int lowbit(int x)6.//计算2^k7.{8. x=x&-x;9. return x;10.}11.void update(int num,int val)12.//向下查询,num是要更新的子节点,val是要修改的值13.{14. while(num>0)15. {16. c[num]+=val;17. num-=lowbit(num);18. }19.}20.int getSum(int num)21.//向上统计每个区间被染色的次数22.{23. int sum=0;24. while(num<=n)25. {26. sum+=c[num];27. num+=lowbit(num);28. }29. return sum;30.}31.int main()32.{33. int a,b;34. while(scanf("%d",&n),n)35. {36. memset(c,0,sizeof(c));37. for(int i=0;i<n;i++)38. {39. scanf("%d%d",&a,&b);40. //将b以下区间+141. update(b,1);42. //将a以下区间-143. update(a-1,-1);44. }45. for(int j=1;j<n;j++)46. {47. printf("%d ",getSum(j));48. }49. printf("%d\n",getSum(n));50. }51. return 0;52.}9.Kmp模板#include<stdio.h>#include<string.h>#include<iostream>using namespace std;#define N 1000010int len,len1,next[N];int str[N],str1[N];void get_next(){int i=0,j=-1;next[0]=-1;while(i<=len1){if(j==-1||str1[i]==str1[j]){i++;j++;next[i]=j;}elsej=next[j];}}int kmp(){int i=0,j=0;{if(j==-1||str[i]==str1[j]) {i++;j++;}else{j=next[j];}}if(j>=len1){return i-len1+1;}return 0;}int main(){int i,t,flag;scanf("%d",&t);while(t--){memset(str,0,sizeof(str));memset(str1,0,sizeof(str1));memset(next,0,sizeof(next));scanf("%d%d",&len,&len1);for(i=0;i<len;i++)scanf("%d",&str[i]);for(i=0;i<len1;i++)scanf("%d",&str1[i]);get_next();flag=kmp();// p rintf("%d\n",flag);if(flag==0)printf("-1\n");elseprintf("%d\n",flag);}return 0; }计算出字符串 str2 中含有的 str1 的个数#include<stdio.h>#include<string.h>int next[10005];char str1[10005], str2[1000005];int n, m, ans;void getNext(char *p, int *next){int j, k;next[0] = -1;j = 0;k = -1;while(j < m){if(k == -1 || p[j] == p[k]) //匹配的情况下,p[j]==p[k]{j++;k++;next[j] = k;//printf("%d **%d **%d\n",j, k, next[j]);}else//p[j]!=p[k]k = next[k];}}int KMPMatch(char *s, char *p){int i = 0, j = 0;getNext(p, next);/*for(i = 1; i < m; i++) printf("%d ", next[i]);i = 0; printf("\n");*/while(i < n){if(j == -1 || s[i] == p[j]){i++;j++;}else{j = next[j]; //消除了指针i的回溯printf("i = %d, j = %d\n", i, j), }if(j == m )ans++;//return i - m + 1;}return ans;}int main(){int T;scanf("%d",&T);while(T--){memset(str1, '\0', sizeof(str1));memset(str2, '\0', sizeof(str2));memset(next, 0, sizeof(next));ans = 0;scanf("%s", str1);scanf("%s", str2);n = strlen(str2);m = strlen(str1);printf("%d\n",KMPMatch(str2, str1));}return 0;}10.线段树(点跟新)#include<stdio.h>#include<string.h>#define N 200010struct Node{int l,r,max;}node[3*N];int score[N];int max(int a,int b){return a>b?a:b;}void Build(int left,int right,int index) {node[index].l=left;node[index].r=right;if(left==right)node[index].max=score[left];else{int mid;mid=(left+right)/2;Build(left,mid,index*2);Build(mid+1,right,index*2+1);node[index].max=max(node[2*index].max,n ode[2*index+1].max);}}void Update(int stu,int c,int index){node[index].max=max(c,node[index].max);if(node[index].l==node[index].r){return ;}if(stu<=node[2*index].r){Update(stu,c,index*2);}else{Update(stu,c,index*2+1);}}int query(int left,int right,int index) {if(left==node[index].l&&right==node[ind ex].r){return node[index].max;}if(right<=node[2*index].r){return query(left,right,index*2);}if(left>=node[2*index+1].l){return query(left,right,index*2+1);}intmid=(node[index].l+node[index].r)/2;returnmax(query(left,mid,2*index),query(mid+1,r ight,index*2+1));}int main(){int n,m;while(scanf("%d%d",&n,&m)!=EOF) {int i;for(i=1;i<=n;i++)scanf("%d",&score[i]);getchar();char c;int s,e;Build(1,n,1);for(i=0;i<m;i++){scanf("%c%d%d",&c,&s,&e);getchar();if(c=='U'){Update(s,e,1);}if(c=='Q'){printf("%d\n",query(s,e,1));}}}return 0;11.强连通# include<stdio.h># include<string.h># define N 1005# define M 2005struct node{int from,to,next;}edge1[M],edge2[M];intvisit1[N],visit2[N],head1[N],head2[N],T[N ];intin_degree[N],out_degree[N],tol1,tol2,Bcnt ,Tcnt;int val[N],v1[N],min,Belong[N];。
ACM比赛用的简单模板
邵伯仲的模板凸包以斜率为基准的gr法#include<iostream>#include<algorithm>#include<vector>#include<math.h>using namespace std;typedef struct{int x,y;double k;}Node;Node *a;bool cmp(const Node &a,const Node &b)// 根据斜率和x进行排序{if (a.k==b.k) return a.x<b.x;return a.k<b.k;}bool mutiply(const Node &one,const Node &two,const Node &three)//差集{double p1x,p1y,p2x,p2y,result;p1x=two.x-one.x;p1y=two.y-one.y;p2x=three.x-one.x;p2y=three.y-one.y;result=p1x*p2y-p2x*p1y;if (result<=0) return true;return false;}double Area(const Node &one,const Node &two)//计算面积{double p1x,p1y,p2x,p2y,result;p1x=one.x-0;p1y=one.y-0;p2x=two.x-0;p2y=two.y-0;result=(p1x*p2y-p2x*p1y)/2;return result;}int main(){double sum;int last,count;vector <Node>s;Node one,two,three;int n,i,min,t;cin>>t;while(t--){cin>>n;a=new Node[n];sum=0;min=0;for(i=0;i<n;i++){cin>>a[i].x>>a[i].y;if (a[min].x>=a[i].x){if (a[min].x>a[i].x||a[min].y>a[i].y) min=i; }}if (n<3) {cout<<"0.0"<<endl;continue;}for(i=0;i<n;i++)//计算斜率{a[i].k=(double)(a[i].y-a[min].y)/(double)(a[i].x+1-a[min].x); }a[min].k=-2100000000;sort(a,a+n,cmp);//按斜率和x排序s.push_back(a[0]);//开始形成凸包s.push_back(a[1]);for(i=2;i<n;i++){last=s.size();two=s[last-1];one=s[last-2];while(mutiply(one,two,a[i])&&i<n&&s.size()>=2){s.pop_back();if(s.size()==1) break;last=s.size();two=s[last-1];one=s[last-2];}s.push_back(a[i]);}//形成了凸包last=s.size();//计算面积one=s[0];two=s[1];for(i=2;i<last;i++){sum+=Area(one,two);one=two;two=s[i];}sum+=Area(one,two);one=two;two=s[0];sum+=Area(one,two);printf("%.1f\n",sum);s.clear();}return 0;}筛法筛法处理素数#include<iostream>#include<cmath>using namespace std;#define MAX 1001bool la[MAX];void pick(){int i,j;memset(la,1,sizeof(la));la[1]=0;for(i=2;i<=sqrt(double(MAX-1));++i) {if (la[i]){for(j=i*i;j<=MAX-1;j+=i){la[j]=0;}}}}int main(){int i;pick();for(i=1;i<MAX;++i){if (la[i]) printf("%d ",i);}putchar('\n');return 0;}队列的stl实现#include <iostream>#include <queue>#include<vector>int main(){std::queue<int> a;std::priority_queue<int,std::vector<int>,std::less<int> > q;q.push(1);q.push(2);std::cout<<q.top()<<std::endl;return 0;}大数问题1 大数之整数加法#include<iostream>#include<string>using namespace std;string plus(const string &a,const string &b){string result,ttemp;int alen,blen,i,j;int add,temp;alen=a.size();blen=b.size();add=0;for(i=alen-1,j=blen-1;i>=0&&j>=0;i--,j--){temp=add+((int)a[i]-48)+((int)b[j]-48);add=temp/10;ttemp.push_back(temp%10+48);result.insert(0,ttemp);ttemp.clear();}while(i>=0){for(;i>=0;i--){temp=add+(a[i]-48);add=temp/10;ttemp.push_back(temp%10+48);result.insert(0,ttemp);ttemp.clear();}}while(j>=0){for(;j>=0;j--){temp=add+(b[j]-48);add=temp/10;ttemp.push_back(temp%10+48);result.insert(0,ttemp);ttemp.clear();}}if (add!=0){ttemp.push_back(add+48);result.insert(0,ttemp);ttemp.clear();}return result;}int main(){string a,b;a="";while(cin>>b&&b!="0"){a=plus(a,b);}cout<<a<<endl;return 0;}2计算大数小数乘法9位运算#include<iostream>#include<string>#include<cstring>using namespace std;void de0(string &s)//删除无效0{int slen,i;slen=s.length();if (s.find(".")!=-1){i=slen-1;while(s[i]=='0'||s[i]=='.'){if (s[i]=='.') {s.erase(i,1);break;}s.erase(i,1);i--;}}slen=s.length();while(s[0]=='0'&&s[1]!='.'&&slen!=1){s.erase(0,1);slen=s.length();}}int dex(string &multiplicand,string &multiplicator)//统计小数的位数并去掉小数点{int x1,x2,mcandlen,mtorlen,candloca,torloca;mcandlen=multiplicand.length();mtorlen=multiplicator.length();candloca=multiplicand.find(".");torloca=multiplicator.find(".");if (candloca!=-1) {x1=mcandlen-candloca-1;multiplicand.erase(candloca,1); }else x1=0;if (torloca!=-1) {x2=mtorlen-torloca-1;multiplicator.erase(torloca,1);}else x2=0;return x1+x2;}string multiplication( string &multiplicand,string &multiplicator) {int candlen,torlen,i,j,count,candg=0,torg=0,slen;__int64 *result,temp,*get_cand,*get_tor;string ch;string xresult;string str;int xlen;de0(multiplicand);de0(multiplicator);if (multiplicand=="0"||multiplicator=="0") return "0";xlen=dex(multiplicand,multiplicator);candlen=multiplicand.length();torlen=multiplicator.length();get_cand=new __int64[candlen/9+2];get_tor=new __int64[torlen/9+2];memset(get_cand,0,sizeof(get_cand));memset(get_tor,0,sizeof(get_tor));count=1;while (multiplicand.length()>=9){str=multiplicand.substr(multiplicand.length()-9);multiplicand.erase(multiplicand.length()-9);get_cand[count]=atoi(str.c_str());++count;}if (!multiplicand.empty()){str=multiplicand;multiplicand.clear();get_cand[count]=atoi(str.c_str());candg=count;}if (candg==0) candg=count-1;count=1;while (multiplicator.length()>=9){str=multiplicator.substr(multiplicator.length()-9);multiplicator.erase(multiplicator.length()-9);get_tor[count]=atoi(str.c_str());++count;}if (!multiplicator.empty()){str=multiplicator;multiplicator.clear();get_tor[count]=atoi(str.c_str());torg=count;}if (torg==0) torg=count-1;result=new __int64[candg*torg+2];for(i=1;i<=candg*torg+1;i++)result[i]=0;for(i=1;i<=candg;i++){for(j=1;j<=torg;j++){result[i+j-1]+=get_cand[i]*get_tor[j];result[i+j]+=result[i+j-1]/1000000000;result[i+j-1]=result[i+j-1]%1000000000;}}i=candg*torg+1;str.clear();while(result[i]==0) i--;temp=result[i];while(temp){ch.push_back(temp%10+48);str.insert(0,ch);ch.clear();temp/=10;}i--;xresult.append(str);str.clear();while(i>=1){temp=result[i--];while(temp){ch.push_back(temp%10+48);str.insert(0,ch);ch.clear();temp/=10;}slen=(int)str.length();if (slen<9){for(j=1;j<=9-slen;j++){str.insert(0,"0");}}xresult.append(str);str.clear();}if (xlen>0){slen=xresult.length();xresult.push_back(' ');count=0;for(i=xresult.length()-1;i>=0;i--){xresult[i]=xresult[i-1];count++;if (count==xlen) {xresult[i-1]='.';break;}if (count<xlen&&i==1) {xresult.insert(0,"0");i++;}}if (i==1) xresult.insert(0,"0");}de0(xresult);delete[] result;//(比赛时可以考虑不释放以节省时间)delete[] get_cand;delete[] get_tor;return xresult;}int main(){string s,t;while(cin>>s>>t)cout<<multiplication(s,t)<<endl;return 0;}大整数乘法/****** Big Number Multiplication *********************/#include<stdio.h>#include<stdlib.h>#include<string.h>#include<math.h>#define MAX 1000/******************************************************************/ void reverse(char *from, char *to ){int len=strlen(from);int i;for(i=0;i<len;i++)to[i]=from[len-i-1];to[len]='\0';}/******************************************************************/void call_mult(char *first,char *sec,char *result){char F[MAX],S[MAX],temp[MAX];int f_len,s_len,f,s,r,t_len,hold,res;f_len=strlen(first);s_len=strlen(sec);reverse(first,F);reverse(sec,S);t_len=f_len+s_len;r=-1;for(f=0;f<=t_len;f++)temp[f]='0';temp[f]='\0';for(s=0;s<s_len;s++){hold=0;for(f=0;f<f_len;f++){res=(F[f]-'0')*(S[s]-'0') + hold+(temp[f+s]-'0');temp[f+s]=res%10+'0';hold=res/10;if(f+s>r) r=f+s;}while(hold!=0){res=hold+temp[f+s]-'0';hold=res/10;temp[f+s]=res%10+'0';if(r<f+s) r=f+s;f++;}}for(;r>0 && temp[r]=='0';r--);temp[r+1]='\0';reverse(temp,result);}/***************************************************************/int main(){char fir[MAX],sec[MAX],res[MAX];while(scanf("%s%s",&fir,&sec)==2){call_mult(fir,sec,res);int len=strlen(res);for(int i=0;i<len;i++)printf("%c",res[i]);printf("\n");}return 0;}大整数除法//***** Big Number division *********************//#include<stdio.h>#include<stdlib.h>#include<string.h>#include<math.h>#define MAX 1000/*******************************************************************/ int call_div(char *number,long div,char *result){int len=strlen(number);int now;long extra;char Res[MAX];for(now=0,extra=0;now<len;now++){extra=extra*10 + (number[now]-'0');Res[now]=extra / div +'0';extra%=div;}Res[now]='\0';for(now=0;Res[now]=='0';now++);strcpy(result, &Res[now]);if(strlen(result)==0)strcpy(result, "0");return extra;}/*******************************************************************/ int main(){char fir[MAX],res[MAX];long sec,remainder;while(scanf("%s%ld",&fir,&sec)==2){if(sec==0) printf("Divide by 0 error\n");else{remainder=call_div(fir,sec,res); int len=strlen(res);for(int i=0;i<len;i++)printf("%c",res[i]);printf("\t%ld",remainder); //余数 printf("\n");}}return 0;}大整数加法#include<stdio.h>#include<stdlib.h>#include<string.h>#include<math.h>#define MAX 1000void reverse(char *from, char *to ){int len=strlen(from);int l;for(l=0;l<len;l++)to[l]=from[len-l-1];to[len]='\0';}void call_sum(char *first, char *sec, char *result){char F[MAX], S[MAX], Res[MAX];int f,s,sum,extra,now;f=strlen(first);s=strlen(sec);reverse(first,F);reverse(sec,S);for(now=0,extra=0;(now<f && now<s);now++){sum=(F[now]-'0') + (S[now]-'0') + extra; Res[now]=sum%10 +'0';extra= sum/10;}for(;now<f;now++){sum=F[now] + extra-'0';Res[now]=sum%10 +'0';extra=sum/10;}for(;now<s;now++){sum=F[now] + extra-'0';Res[now]=sum%10 +'0';extra=sum/10;}if(extra!=0) Res[now++]=extra+'0';Res[now]='\0';if(strlen(Res)==0) strcpy(Res,"0");reverse(Res,result);}int main(){char fir[MAX],sec[MAX],res[MAX];while(scanf("%s%s",&fir,&sec)==2){call_sum(fir,sec,res);int len=strlen(res);for(int i=0;i<len;i++) printf("%c",res[i]);printf("\n");}return 0;}大整数减法/***** Big Number Subtraction *******************/#include<stdio.h>#include<stdlib.h>#include<string.h>#include<math.h>#define MAX 1000/*******************************************************************/ void reverse(char *from, char *to ){int len=strlen(from);int l;for(l=0;l<len;l++)to[l]=from[len-l-1];to[len]='\0';}int call_minus(char *large, char *small, char *result){char L[MAX], S[MAX];int l,s,now,hold,diff;l=strlen(large);s=strlen(small);bool sign = 0;if(l<s){strcpy(result,large);strcpy(large,small);strcpy(small,result);now=l; l=s; s=now;sign = 1;}//return 0;if(l==s){if(strcmp(large, small)<0){strcpy(result,large);strcpy(large,small);strcpy(small,result);now=l; l=s; s=now;sign =1;}//return 0;}reverse(large,L);reverse(small,S);for(;s<l;s++)S[s]='0';S[s]='\0';for(now=0,hold=0;now<l;now++){diff=L[now]-(S[now]+hold);if(diff<0){hold=1;result[now]=10+diff+'0'; }else{result[now]=diff+'0';hold=0;}}for(now=l-1;now>0;now--){if(result[now]!='0')break;}result[now+1]='\0';reverse(result,L);strcpy(result,L);//return 1;return sign;}int main(){char fir[MAX],sec[MAX],res[MAX];while(scanf("%s%s",&fir,&sec)==2){if(call_minus(fir,sec,res)==1) printf("-");int len = strlen(res);for(int i=0;i<len;i++)printf("%c",res[i]);printf("\n");}return 0;}大整数开平方根//****** Big Number Sqrt ************************//#include<stdio.h>#include<stdlib.h>#include<string.h>#include<math.h>#define MAX 1000/******************************************************************/ void reverse(char *from, char *to ){int len=strlen(from);int i;for(i=0;i<len;i++)to[i]=from[len-i-1];to[len]='\0';}/****************************************************************/ int call_minus(char *large, char *small, char *result){char L[MAX], S[MAX];int l,s,now,hold,diff;l=strlen(large);s=strlen(small);if(l<s)return 0;if(l==s){if(strcmp(large, small)<0)return 0;}reverse(large,L);reverse(small,S);for(;s<l;s++)S[s]='0';S[s]='\0';for(now=0,hold=0;now<l;now++){diff=L[now]-(S[now]+hold);if(diff<0){hold=1;result[now]=10+diff+'0';}else{result[now]=diff+'0';hold=0;}}for(now=l-1;now>0;now--){if(result[now]!='0')break;}result[now+1]='\0';reverse(result,L);strcpy(result,L);return 1;}/******************************************************************/ void call_mult(char *first,char *sec,char *result){char F[MAX],S[MAX],temp[MAX];int f_len,s_len,f,s,r,t_len,hold,res;f_len=strlen(first);s_len=strlen(sec);reverse(first,F);reverse(sec,S);t_len=f_len+s_len;r=-1;for(f=0;f<=t_len;f++)temp[f]='0';temp[f]='\0';for(s=0;s<s_len;s++){hold=0;for(f=0;f<f_len;f++){res=(F[f]-'0')*(S[s]-'0') + hold+(temp[f+s]-'0');temp[f+s]=res%10+'0';hold=res/10;if(f+s>r) r=f+s;}while(hold!=0){res=hold+temp[f+s]-'0';hold=res/10;temp[f+s]=res%10+'0';if(r<f+s) r=f+s;f++;}}for(;r>0 && temp[r]=='0';r--);temp[r+1]='\0';reverse(temp,result);}/****************************************************************/ void call_sqrt(char *number,char *result,char *extra){int num,start,e,mul,l,r=0,len;char left[MAX],after[MAX];char who[5],temp[MAX],two[5];len=strlen(number);if(len%2==0){num=10*(number[0]-'0') + number[1]-'0';start=2;}else{num=number[0]-'0';start=1;}mul=(int) sqrt(num);result[0]=mul+'0';result[1]='\0';if(num-mul*mul ==0)extra[0]='\0';elsesprintf(extra,"%d",num-mul*mul);for(;start<len;start+=2){e=strlen(extra);extra[e]=number[start];extra[e+1]=number[start+1];extra[e+2]='\0';two[0]='2';two[1]='\0';call_mult(result,two,left);l=strlen(left);for(mul=9;mul>=0;mul--){who[0]=mul+'0';who[1]='\0';strcat(left,who);call_mult(left,who,after);if(call_minus(extra,after,temp)==1){result[++r]=mul+'0';result[r+1]='\0';strcpy(extra,temp);break;}elseleft[l]='\0';}}result[++r]='\0';}/******************************************************************/ int main(){char fir[MAX],ex[MAX],res[MAX];while(scanf("%s",&fir)==1){call_sqrt(fir,res,ex);int len=strlen(res);for(int i=0;i<len;i++) printf("%c",res[i]);printf("\n");}return 0;}孩子报数问题:#include<stdio.h>#include<string.h>typedef struct{char name[16];}Name;int main(){Name child[65];int n,count,i,j,k;scanf("%d",&n);for(i=1;i<=n;i++){scanf("%s",&child[i].name);}scanf("%d,%d",&count,&k);for(i=n;i>=2;--i){count=(count+k-1)%i;if (count==0) count=i;printf("%s\n",child[count].name);for(j=count;j<i;++j){strcpy(child[j].name,child[j+1].name);}}printf("%s\n",child[1].name);return 0;}统计难题:Ignatius最近遇到一个难题,老师交给他很多单词(只有小写字母组成,不会有重复的单词出现),现在老师要他统计出以某个字符串为前缀的单词数量(单词本身也是自己的前缀).输入输入数据的第一部分是一张单词表,每行一个单词,单词的长度不超过10,它们代表的是老师交给Ignatius统计的单词,一个空行代表单词表的结束.第二部分是一连串的提问,每行一个提问,每个提问都是一个字符串.注意:本题只有一组测试数据,处理到文件结束.输出对于每个提问,给出以该字符串为前缀的单词的数量.样例输入bananabandbeeabsoluteacmbabbandabc样例输出231字典树解决:#include<iostream>#include<string.h>using namespace std;typedef struct Node{char letter;bool la;struct Node *child;struct Node *brother;int count;}Elem;void creat(Elem *head,char *word){Elem *p,*q,*r;int i;bool suc;p=head;for(i=0;i<(int)strlen(word);i++){suc=false;q=p->child;r=q;while(q){r=q;if (q->letter==word[i]) {suc=true;p=q;p->count++;break;}q=q->brother;}if (suc) continue;q=new Elem;q->letter=word[i];q->count=1;q->brother=NULL;q->child=NULL;q->la=false;if (!p->child) p->child=q;if (r) r->brother=q;p=q;}}int find_1(Elem head,char *word){Elem *p,*q;int i;p=&head;for(i=0;i<(int)strlen(word);i++){q=p->child;while(q){if (q->letter==word[i]) {break;}q=q->brother;}if (!q) return 0;p=q;}return p->count;}int main(){char word[10];Elem head;head.letter=0;head.child=NULL;head.brother=NULL;=true;head.count=0;while(gets(word),strcmp(word,"")!=0){creat(&head,word);}while(scanf("%s",word)!=EOF){printf("%d\n",find_1(head,word));}return 0;}21。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
13.求两条线段的交点 ........................................................................................................ 35 四、数论 ................................................................................................................................. 36
10.Ronberg 算法计算积分 ................................................................................................. 12 11.行列式计算 .................................................................................................................... 14 12.求排列组合数 ................................................................................................................ 14 13.求某一天星期几 ............................................................................................................ 151 / 76 NhomakorabeaU
nR
16.全排列 ............................................................................................................................ 17
eg
14.卡特兰 (Catalan) 数列 原理 ....................................................................................... 15
15.杨辉三角 ........................................................................................................................ 16
17.匈牙利算法----最大匹配问题. ...................................................................................... 18 18.最佳匹配 KM 算法........................................................................................................ 19 二、字符串处理 ..................................................................................................................... 22 1.字符串替换 ...................................................................................................................... 22 2.字符串查找 ...................................................................................................................... 23 3.字符串截取 ...................................................................................................................... 23 4.LCS-最大公共子串长度 ................................................................................................. 24 5.LCS-最大公共子串长度 ................................................................................................. 25 6.数字转换为字符 .............................................................................................................. 25 三、计算几何 ......................................................................................................................... 26 1.叉乘法求任意多边形面积 .............................................................................................. 26
is
te
re
9.快速傅立叶变换(FFT) ............................................................................................... 10
d
8.组合序列 ............................................................................................................................ 9
2.返回 x 的二进制表示中从低到高的第 i 位 ................................................................... 37 3.模取幂运算 ...................................................................................................................... 37
ACM 计算机学院 USTAR 团队 整理
目录
一、数学问题 ........................................................................................................................... 4 1.精度计算——大数阶乘 .................................................................................................... 4 2.精度计算——乘法(大数乘小数) ................................................................................ 4 3.精度计算——乘法(大数乘大数) ................................................................................ 5 4.精度计算——加法 ............................................................................................................ 6 5.精度计算——减法 ............................................................................................................ 7 6.任意进制转换 .................................................................................................................... 8 7.最大公约数、最小公倍数 ................................................................................................ 9
ACM 计算机学院 USTAR 团队 整理
2.求三角形面积 .................................................................................................................. 27 3.两矢量间角度 .................................................................................................................. 27 4.两点距离(2D、3D) .................................................................................................... 28 5.射向法判断点是否在多边形内部 .................................................................................. 28 6.判断点是否在线段上 ...................................................................................................... 29 7.判断两线段是否相交 ...................................................................................................... 30 8.判断线段与直线是否相交 .............................................................................................. 31 9.点到线段最短距离 .......................................................................................................... 32 10.求两直线的交点 ............................................................................................................ 32 11.判断一个封闭图形是凹集还是凸集 ............................................................................ 33