acm 算法模板

合集下载

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模版

大数除法16进制#include <stdio.h>#include <string.h>#define max 200int i;char jinzhi[16]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; int chu(char a[],char b[]){int shan, yu;for(yu = i = 0; a[i]; i++){yu = yu * 10 + a[i] - '0';shan = yu / 16;yu = yu % 16;b[i] = shan + '0';}b[i] = 0;return yu;}int judge(char a[]){for(i = 0; a[i]; i++)if(a[i] != '0')return 0;return 1;}void f(char a[]){int newbig;if(!judge(a)){char b[max];newbig = chu(a,b);f(b);printf("%c",jinzhi[newbig]);}}int main(void){char bigint[max];while(scanf("%s", bigint) == 1){if(strlen(bigint) == 1 ){if(bigint[0] == '0')return 0;}f(bigint);printf("\n");memset(bigint,'0',sizeof(bigint));}return 0;}最大公约数int GCD(int num1,int num2)//最大公约数{if ( num1 % num2 == 0){return num2;}elsereturn GCD( num2,num1 % num2) ;}最小公倍数int LCM(int a,int b)//最小公倍数{int temp_lcm;temp_lcm=a*b/GCD(a,b); //最小公倍数等于两数之积除以最大公约数return temp_lcm;}//求至少多少天相遇,同时出发,至少多少长方形堆正方体,分元宝类问题都是运用最小公倍数最小生成树#include<iostream>#include<cstdlib>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>using namespace std;const int inf = ( 1 << 20 ) ;int p[27]; // 并查集,用于判断两点是否直接或间接连通struct prog{int u;int v;int w;}map[80];//存储边的信息,包括起点/终点/权值bool cmp ( prog a , prog b){//排序函数,将边根据权值从小到大排return a.w<b.w;}int find(int x){//并查集的find,不解释return x==p[x]?x:p[x]=find(p[x]);}//减枝void join(int x,int y,int i){int fx=find(x),fy=find(y);if(fx!=fy){pre[fx]=fy;if(i!=-1) fee+=a[i].x;}return;}int main(){int n;while ( cin >> n , n ){int i , j ;for ( i = 0 ; i < 27 ; i ++ )p[i] = i ;//并查集初始化int k = 0 ;for ( i = 0 ; i < n - 1 ; i ++ ){//构造边的信息char str[3];int m;cin >> str >> m ;for ( j = 0 ; j < m ; j ++ ,k ++ ){char str2[3];int t;cin >> str2 >> t ;map[k].u=(str[0]-'A');map[k].v=(str2[0]-'A');map[k].w=t;}}sort ( map , map + k , cmp );//将边从小到大排序int ans=0; //所要求的答案for ( i = 0 ; i < k ; i ++ ){int x = find(map[i].u);int y = find(map[i].v);printf("%d%d\n",x,y);if( x!=y){//如果两点不在同一连通分量里,则将两点连接,并存储该边ans+=map[i].w;p[x]=y;}}cout<<ans<<endl;}return 0;}最大连续子序列-1235#include <stdio.h>#include <math.h>#include <string.h>#include <algorithm>int a[10010],maxsum,t,e,n;void ff(){int i,l,j,sum;for(i = 0; i < n; i++){sum = 0;for(l = i; l < n; l++){sum += a[l];if(sum > maxsum){maxsum = sum;t = i;e = l;// printf("%d\n",maxsum);}// printf("%d %d %d\n",i,l,sum);}}}int main(){//freopen("1235input.txt","r",stdin);int f,i;while(scanf("%d",&n)&&n){memset(a,0,sizeof(a));f =0;maxsum = -10000;for(i = 0; i < n; i++){scanf("%d",&a[i]);if(a[i] < 0)f++;}if(f == n){maxsum = 0;t = 0;e = n-1;}elseff();printf("%d %d %d\n",maxsum,a[t],a[e]);}return 0;}素数表int a[10000];//1为素数void ff(){memset(a,1,sizeof(a));for(i=2;i<=10000;i++){if(a[i]==1){printf("%d ",i);for(l=i;l<=10000;l++){if(a[l]==1)if(l%i==0)a[l]=0;}}}}================int a[10000];void ff(){memset(a,1,sizeof(a));for(int i = 2; i < 10000; i++){if(a[i] == 0){int l = i;while(i * l < 10000){a[i*l]=0;l++;} }}}BFSinclude <stdio.h>#include <string.h>int x, y, mx, my,step;char map[110][110];int move[8][2]={-1,-1,-1,0,-1,1,0,-1,0,1,1,-1,1,0,1,1};int recode[110][110];int f[110][110];struct duili{int x;int y;}a[110*110];bool judge(int m, int n){if(map[m][n]== '.' &&f[m][n]==2&& m>0 &&n>0&&m<y+1&&n<x+1) return 1;elsereturn 0;}int bfs(int i,int j){int front = 0,rear = 1;step = -1;recode[i][j] = 0; f[i][j]=1;a[front].x = i;a[front].y = j;while(front < rear){int xx = a[front].x, yy = a[front].y;front++;for(i = 0; i < 8; i++ ){if(judge(xx + move[i][0],yy + move[i][1])){f[xx + move[i][0]][yy + move[i][1]] =1 ;recode[xx + move[i][0]][yy + move[i][1]] = recode[xx][yy] + 1;a[rear].x = xx + move[i][0];a[rear].y = yy + move[i][1];rear++;if (recode[xx + move[i][0]][yy + move[i][1]] > step)step = recode[xx + move[i][0]][yy + move[i][1]];}}// for(int i = y; i > 0; i--)// {// for(int j = 1; j <= x; j++)// printf("%d",f[i][j]);// printf("\n");// }// printf("\n");}return step;}int main(){scanf("%d%d%d%d",&x, &y, &mx, &my);memset(map,0,sizeof(map));memset(f,0,sizeof(f));memset(recode,0,sizeof(recode));getchar();for(int i = y; i > 0; i--){for(int j = 1; j <= x; j++){scanf("%c",&map[i][j]);if(map[i][j]=='.')f[i][j]=2;}getchar();}// for(int i = y; i > 0; i--)// {// for(int j = 1; j <= x; j++)// printf("%c",map[i][j]);// printf("\n");// }printf("%d\n",bfs(mx,my));return 0;}CD_ROOM#include <stdio.h>int maxn;int n;int arr[20];int tempmax;void ff(int cur, int sum){if (sum > maxn)return;if (cur == n){tempmax >?= sum;return;}ff(cur + 1, sum);sum += arr[cur];ff(cur + 1, sum);}int main(void){while (tempmax = 0, scanf("%d", &n) == 1) {scanf("%d", &maxn);for (int i = 0; i < n; i++)scanf("%d", arr + i);ff(0, 0);printf("%d\n", tempmax);}return 0; }Floyed(最短路径)(可以有圈)#include <iostream>#include <string>#include <map>using namespace std;const int MAXN = 31;typedef double ValueType;//数据类型void Floyed(ValueType g[][MAXN],int n)//佛洛依德算法{for(int k=0;k<n;++k)for(int i=0;i<n;++i)for(int j=0;j<n;++j)if(g[i][j]<g[i][k]*g[k][j]) g[i][j] = g[i][k]*g[k][j];//尽可能使汇率大,这里是乘法(*)}int main(){int n,m,i,Case=0;string name,sour,dest;V alueType value;map<string,int> Currency; //用map实现name和index之间的转换V alueType graph[MAXN][MAXN];while(cin>>n){if(n==0) break;Currency.clear();memset(graph,0,sizeof(graph));for(i=0;i<n;++i)//n个顶点{cin>>name;Currency[name] = i;graph[i][i] = 1;}cin>>m;//m条边for(i=0;i<m;++i)//输入边信息创建图{cin>>sour>>value>>dest;graph[Currency[sour]][Currency[dest]] = value;}Floyed(graph,n);//佛洛依德求各个节点之间的bool ok = false;for(int i=0;i<n;++i)//求自身到自身的汇率(回路) if(graph[i][i]>1){ok=true;break;}cout<<"Case "<<++Case<<": ";if(ok) cout<<"Yes\n";else cout<<"No\n";}return 0;}3个for#include<stdio.h>#define MAX 100000000int main(){int n,m,a,b,t,i,j,k,map[202][202];while(scanf("%d%d",&n,&m)!=EOF){for(i=1;i<=n;i++)for(j=1;j<=n;j++)map[i][j]=MAX;while(m--){scanf("%d%d%d",&a,&b,&t);map[a][b]=t;map[b][a]=t;}for(k=1;k<=n;k++)for(i=1;i<=n;i++)for(j=1;j<=n;j++)if(map[i][k]+map[k][j]<map[i][j])map[i][j]=map[i][k]+map[k][j];scanf("%d%d",&a,&b);if(map[a][b]==MAX||b>n||a<1)printf("-1\n");elseprintf("%d\n",map[a][b]);}}Dijkstra算法+注释#include <iostream>#include <string.h>#include <limits.h>#include <stdio.h>//hdu1874using namespace std;int map[1002][1002];int main(){int n,m;while(~scanf("%d%d",&n,&m)){int visted[205],dis[205];memset(visted,0,sizeof(visted)); //访问数组初始化for(int i=1;i<=n;++i){dis[i]=INT_MAX; //初始化两点之间的最短路径!!for(int j=1;j<=n;++j)map[i][j]=INT_MAX; //初始化两点间距离!!map[i][i]=0;}int a,b,c;while(m--){scanf("%d%d%d",&a,&b,&c);//输入两点间最短距离if(c<map[a][b])map[a][b]=map[b][a]=c;}int begin ,end ,pos;scanf("%d%d",&begin,&end);pos=begin;visted[pos]=1;//访问初始起始点。

我的ACM算法模板

我的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数论相关模板

ACM数论相关模板

求最大公约数(欧几里得算法)int gcd(int a, int b){if (b == 0) return a;return gcd(b, a % b);}求最小公倍数Lcm(a, b) = a * b / gcd(a, b);判断是否为素数#include <iostream>#include <stdio.h>#include <math.h>using namespace std;bool judgeprime(int n){bool flag =true;int m = sqrt(n);for (int i = 2; i <= m; i++){if (n % i == 0){flag = false;break;}}if (flag) printf("yes\n");else printf("no\n");}快速幂求%yx pLong long pw(long long x, long long y,long long p){if (y == 0) return 1LL;long long tmp = pw (x, y / 2, p);if (y & 1) return tmp * tmp % p * x % p;return tmp * tmp % p;}埃拉托斯特尼筛法寻找n 以内的素数 void findprime(int n){bool isprime[10005];int prime[10005], i, j, total;memset(isprime, true, sizeof(isprime));total=0;for (i = 2; i<=n; i++){if (isprime[i]){prime[total++] = i;for (j=i*i;j<=n;j+=i)isprime[j]=false;}}for (i = 0; i < total; i++)printf("%d ",prime[i]);}欧拉筛法void makePrime(){memset(isPrime,true,sizeof(isPrime));for(int i=2; i<=MAXN; i++){if(isPrime[i]) prime[total++]=i;for(int j=0; j<total && i*prime[j]<=MAX; j++){isPrime[i*prime[j]]=false;//i此时不是素数,只是拓展用if(i%prime[j]==0) break;}}}。

ACM程序竞赛计算几何超全模板

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算法--枚举⽅法(指数枚举,组合枚举)模板// 递归实现指数型枚举vector<int> chosen;void calc(int x) {if (x == n + 1) {for (int i = 0; i < chosen.size(); i++)printf("%d ", chosen[i]);puts("");return;}calc(x + 1);chosen.push_back(x);calc(x + 1);chosen.pop_back();}// 递归实现组合型枚举vector<int> chosen;void calc(int x) {if (chosen.size() > m || chosen.size() + (n - x + 1) < m) return;if (x == n + 1) {for (int i = 0; i < chosen.size(); i++)printf("%d ", chosen[i]);puts("");return;}calc(x + 1);chosen.push_back(x);calc(x + 1);chosen.pop_back();}// 递归实现排列型枚举int order[20];bool chosen[20];void calc(int k) {if (k == n + 1) {for (int i = 1; i <= n; i++)printf("%d ", order[i]);puts("");return;}for (int i = 1; i <= n; i++) {if (chosen[i]) continue;order[k] = i;chosen[i] = 1;calc(k + 1);chosen[i] = 0;order[k] = 0;}}// 模拟机器实现,把组合型枚举改为⾮递归vector<int> chosen;int stack[100010], top = 0, address = 0;void call(int x, int ret_addr) { // 模拟计算机汇编指令callint old_top = top;stack[++top] = x; // 参数xstack[++top] = ret_addr; // 返回地址标号stack[++top] = old_top; // 在栈顶记录以前的top值}int ret() { // 模拟计算机汇编指令retint ret_addr = stack[top - 1];top = stack[top]; // 恢复以前的top值return ret_addr;}int main() {int n, m;cin >> n >> m;call(1, 0); // calc(1)while (top) {int x = stack[top - 2]; // 获取参数switch (address) {case 0:if (chosen.size() > m || chosen.size() + (n - x + 1) < m) {address = ret(); // returncontinue;}if (x == n + 1) {for (int i = 0; i < chosen.size(); i++)printf("%d ", chosen[i]);puts("");address = ret(); // returncontinue;}call(x + 1, 1); // 相当于calc(x + 1),返回后会从case 1继续执⾏ address = 0;continue; // 回到while循环开头,相当于开始新的递归case 1:chosen.push_back(x);call(x + 1, 2); // 相当于calc(x + 1),返回后会从case 2继续执⾏ address = 0;continue; // 回到while循环开头,相当于开始新的递归case 2:chosen.pop_back();address = ret(); // 相当于原calc函数结尾,执⾏return}}}。

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大赛必备_常用函数整理_ACM模板(整理版)

-【精品资料】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 算法模板

ACM 算法模板

ACM Standard Code LibraryHuang WeiComputer Science and EngineeringAssociation of ProgramingInformation Engineering CollegeHangzhou Dianzi UniversityApril, 2007ACM 算法模板集Contents一.常用函数与STL二.重要公式与定理1. Fibonacci Number2. Lucas Number3. Catalan Number4. Stirling Number(Second Kind)5. Bell Number6. Stirling's Approximation7. Sum of Reciprocal Approximation8. Young Tableau9. 整数划分10. 错排公式11. 三角形内切圆半径公式12. 三角形外接圆半径公式13. 圆內接四边形面积公式14. 基础数论公式三.大数模板四.数论算法1. Greatest Common Divisor最大公约数2. Prime素数判断3. Sieve Prime素数筛法4. Module Inverse模逆元5. Extended Euclid扩展欧几里德算法6. Modular Linear Equation模线性方程(同余方程)7. Chinese Remainder Theorem中国余数定理五.图论算法1. 最小生成树(Kruscal算法)2. 最小生成树(Prim算法)3. 单源最短路径(Bellman-ford算法)4. 单源最短路径(Dijkstra算法)5. 全源最短路径(Folyd算法)6. 拓扑排序7. 网络预流和最大流8. 网络最小费用最大流9. 网络最大流(高度标号预流推进)10. 最大团11. 最大二分图匹配(匈牙利算法)六.几何算法1. 几何模板2. 球面上两点最短距离3. 三点求圆心坐标七.专题讨论1. 树状数组2. 字典树3. 后缀树4. 线段树5. 并查集6. 二叉堆7. 逆序数(归并排序)8. 树状DP9. 欧拉路10. 八数码11. 高斯消元法12. 字符串匹配(KMP算法)13. 全排列,全组合第一章常用函数和STL一.常用函数#include <stdio.h>int getchar( void ); //读取一个字符, 一般用来去掉无用字符char *gets( char *str ); //读取一行字符串#include <stdlib.h>void * malloc( size_t size ); //动态内存分配, 开辟大小为 size 的空间void qsort( void *buf, size_t num, size_t size, int (*compare)(const void *, const void *) ); //快速排序Sample:int compare_ints( const void* a, const void* b ){int* arg1 = (int*) a; int* arg2 = (int*) b;if( *arg1 < *arg2 ) return -1;else if( *arg1 == *arg2 ) return 0;else return 1;}int array[] = { -2, 99, 0, -743, 2, 3, 4 }; int array_size = 7;qsort( array, array_size, sizeof(int), compare_ints );#include <math.h>//求反正弦, arg∈[-1, 1], 返回值∈[-pi/2, +pi/2]double asin( double arg );//求正弦, arg为弧度, 弧度=角度*Pi/180.0, 返回值∈[-1, 1]double sin( double arg );//求e的arg次方double exp( double arg );//求num的对数, 基数为edouble log( double num );//求num的根double sqrt( double num );//求base的exp次方double pow( double base, double exp );#include <string.h>//初始化内存, 常用来初始化数组void* memset( void* buffer, int ch, size_t count );memset( the_array, 0, sizeof(the_array) );//printf是它的变形, 常用来将数据格式化为字符串int sprintf( char *buffer, const char *format, ... );sprintf(s, "%d%d", 123, 4567); //s="1234567"//scanf是它的变形, 常用来从字符串中提取数据int sscanf( const char *buffer, const char *format, ... );Sample:char result[100]="24 hello", str[100]; int num;sprintf( result, "%d %s", num,str );//num=24;str="hello" ;//字符串比较, 返回值<0代表str1<str2, =0代表str1=str2, >0代表str1>str2 int strcmp( const char *str1, const char *str2 );二.常用STL[标准container概要]vector<T> 大小可变的向量, 类似数组的用法, 容易实现删除list<T> 双向链表queue<T> 队列, empty(), front(), pop(), push()stack<T> 栈, empty(), top(), pop(), push()priority_queue<T> 优先队列, empty(), top(), pop(), push()set<T> 集合map<key,val> 关联数组, 常用来作hash映射[标准algorithm摘录]for_each() 对每一个元素都唤起(调用)一个函数find() 查找第一个能与引数匹配的元素replace() 用新的值替换元素, O(N)copy() 复制(拷贝)元素, O(N)remove() 移除元素reverse() 倒置元素sort() 排序, O(N log(N))partial_sort() 部分排序binary_search() 二分查找merge() 合并有序的序列, O(N)[C++ String摘录]copy() 从别的字符串拷贝empty() 判断字符串是否为空erase() 从字符串移除元素find() 查找元素insert() 插入元素length() 字符串长度replace() 替换元素substr() 取子字符串swap() 交换字符串第二章重要公式与定理1.Fibonacci Number0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610 …Formula:2.Lucas Number1, 3, 4, 7, 11, 18, 29, 47, 76, 123...Formula:3.Catalan Number1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, 58786, 208012…Formula:Application:1)将n + 2 边形沿弦切割成n个三角形的不同切割数Sample:n = 2;n = 3;2)n + 1个数相乘, 给每两个元素加上括号的不同方法数Sample:n = 2; (1 (2 3)), ((1 2) 3)n = 3; (1 (2 (3 4))), (1 ((2 3) 4)) , ((1 2) (3 4)), ((1 (2 3)) 4), (((1 2) 3) 4)3)n 个节点的不同形状的二叉树数(严《数据结构》P.155)4)从n * n 方格的左上角移动到右下角不升路径数Sample:n = 2;n = 3;4.Stirling Number(Second Kind)S(n, m)表示含n个元素的集合划分为m个集合的情况数或者是n个有标号的球放到m 个无标号的盒子中, 要求无一为空, 其不同的方案数Formula:Special Cases:5.Bell Numbern 个元素集合所有的划分数Formula:6.Stirling's Approximation7.Sum of Reciprocal ApproximationEulerGamma = 0.57721566490153286060651209;8.Young TableauYoung Tableau(杨式图表)是一个矩阵, 它满足条件:如果格子[i, j]没有元素, 则[i+1, j]也一定没有元素如果格子[i, j]有元素a[i, j],则[i+1, j]要么没有元素, 要么a[i+1, j] > a[i, j] Y[n]代表n个数所组成的杨式图表的个数Formula:Sample:n = 3;9.整数划分将整数n分成k份, 且每份不能为空, 任意两种分法不能相同1) 不考虑顺序for(int p=1; p<=n ;p++)for(int i=p; i<=n ;i++)for(int j=k; j>=1 ;j--)dp[i][j] += dp[i-p][j-1];cout<< dp[n][k] <<endl;2) 考虑顺序dp[i][j] = dp[i-k][j-1]; (k=1..i)3) 若分解出来的每个数均有一个上限mdp[i][j] = dp[i-k][ j-1]; (k=1..m)10.错排公式11.三角形内切圆半径公式12.三角形外接圆半径公式13.圆內接四边形面积公式14.基础数论公式1)模取幂2) n的约数的个数若n满足, 则n的约数的个数为第三章大数模板/**** **** **** **** **** ***** Function Name : BigNumber* Description : BigNumber's HPC* Author : HuangWei* Last Edited : 07.4.11**** **** **** **** **** ****/#include <iostream>#include <string>#include <sstream>#include <memory>#include <algorithm>#define BASE 1000 // 基数#define DIG 1100 // 存储using namespace std;class BigNumber{private:int data[DIG]; // 数据区int len; // 记录长度public:BigNumber() {len=1;memset(data,0,sizeof(data));data[0]=1;}BigNumber(int); // 输入默认十进制BigNumber(char*);BigNumber(const BigNumber &);// 类型转换BigNumber & Num_BNum(int); //把一个整数转换成BigNumber型的BigNumber & Str_BNum(char*); //把一个字符串类型的转换成BigNumber型的int Int();string Str();// HPCBigNumber & Add(const BigNumber &);BigNumber & Sub(const BigNumber &);BigNumber & Mul(const BigNumber &);BigNumber & Div(int);BigNumber & Mod(int);BigNumber & operator=(const BigNumber &);int Bigger(const BigNumber &) const;BigNumber operator + (const BigNumber &);BigNumber operator - (const BigNumber &);BigNumber operator * (const BigNumber &);BigNumber operator / (int);BigNumber operator % (int);BigNumber & operator += (const BigNumber &); BigNumber & operator -= (const BigNumber &); BigNumber & operator *= (const BigNumber &); BigNumber & operator /= (int);BigNumber & operator %= (int);};BigNumber & BigNumber::Num_BNum(int b){len=1; memset(data,0,sizeof(data));data[0] = 1;if(b < 0) {b = -b;data[0] = -1;}while(b > 0) {data[ len++ ] = b % BASE;b /= BASE;}return *this;}BigNumber & BigNumber::Str_BNum(char* sb) {int t=0, d=1, b=0, slen=strlen(sb), i;len=1; memset(data,0,sizeof(data));data[0] = 1;if(sb[0] == '-') data[0] = -1, b=1;for(i=slen-1; i>=b ;i--) {while(t >= BASE || d > BASE) {data[ len++ ] = t % BASE;t /= BASE;d = 10;}t += (sb[i]-'0') * d;d *= 10;}while(t > 0) {data[ len++ ] = t % BASE;t /= BASE;}return *this;}int BigNumber::Int(){istringstream sin;int v;sin.str( this->Str() );sin >> v;return v;} //这个函数的用法还是第一次看到,没看懂string BigNumber::Str(){int i,base_len=0;ostringstream sout;if(len == 1) {sout << '0';//sout << endl;return sout.str();}if(data[0] < 0) sout << "-";sout << data[len-1];i = BASE;while(i > 1) {base_len++;i /= 10;}for(i=len-2; i>0 ;i--) {sout.width(base_len);sout.fill('0');sout << data[i];}//sout << endl;return sout.str();} //这个函数也没有看懂BigNumber::BigNumber(int b){this->Num_BNum(b);}BigNumber::BigNumber(char* sb){this->Str_BNum(sb);}// -1 a<b, 0 a==b, 1 a>bBigNumber::BigNumber(const BigNumber & b){len = b.len; memcpy(data,b.data,sizeof(data));}int BigNumber::Bigger(const BigNumber & b) const {int i,flag;if(data[0] ==1 && b.data[0] ==1) flag = 1;else if(data[0] ==1 && b.data[0] ==-1) return 1;else if(data[0] ==-1 && b.data[0] ==1) return -1;else flag = -1;if(len > b.len) return flag;else if(len == b.len) {for(i=len-1; i>0 ;i--)if(data[i] > b.data[i]) return flag;}if(i == 0) return 0;return -flag;} //比较函数BigNumber & BigNumber::Add(const BigNumber & b) {int i;if(data[0] * b.data[0] != 1) {data[0] = -data[0];Sub(b);data[0] = -data[0];return *this;}len= len > b.len ? len : b.len;for(i=1; i<len ;i++) {data[i] += b.data[i];if(data[i] >= BASE) {data[i+1]++;data[i] -= BASE;}}if(data[i] > 0) len = i+1;return *this;} //加上b这个大数BigNumber & BigNumber::Sub(const BigNumber & b) {int i;if(data[0] * b.data[0] != 1) {data[0] = -data[0];Add(b);data[0] = -data[0];return *this;}len= len > b.len ? len : b.len;for(i=1; i<len ;i++) {data[i] -= b.data[i];if(data[i] < 0) {data[i+1]--;data[i] += BASE;}}if(data[len] < 0) {for(i=0; i<=len ;i++)data[i] = -data[i];for(i=1; i<len ;i++)if(data[i] < 0) {data[i+1]--;data[i] += BASE;}}while(data[len-1] == 0) len--;return *this;}BigNumber & BigNumber::Mul(const BigNumber & b) {BigNumber bt;int i,j,up;int temp,temp1;bt.data[0] = data[0] * b.data[0];for(i=1; i<len ;i++) {up = 0;for(j=1; j<b.len ;j++) {temp = data[i] * b.data[j] + bt.data[i+j-1] + up;if(temp >= BASE) {temp1 = temp % BASE;up = temp / BASE;bt.data[i+j-1] = temp1;}else {up = 0;bt.data[i+j-1] = temp;}}if(up != 0) bt.data[i+j-1] = up;}bt.len = i+j;while(bt.data[bt.len-1] == 0) bt.len--;*this=bt;return *this;}BigNumber & BigNumber::Div(int b){BigNumber bt;int i,down = 0;if(b < 0) bt.data[0] = -data[0] , b = -b;else bt.data[0] = data[0];for(i=len-1; i>=1 ;i--) {bt.data[i] = (data[i] + down * BASE) / b;down = data[i] + down * BASE - bt.data[i] * b;}bt.len = len;while(bt.data[bt.len-1] == 0) bt.len--;*this=bt;return *this;}BigNumber & BigNumber::Mod(int b){int temp = 0, up = 0, i;for(i=len-1; i>=1 ;i--) {temp = data[i];temp += up * BASE;up = temp % b;}if(data[0] < 0) up = -up;*this = up;return *this;}BigNumber & BigNumber::operator = (const BigNumber & b) {len = b.len; memcpy(data,b.data,sizeof(data)); return *this;}BigNumber BigNumber::operator + (const BigNumber & b) {BigNumber bt=*this; return bt.Add(b);}BigNumber BigNumber::operator - (const BigNumber & b) {BigNumber bt=*this; return bt.Sub(b);}BigNumber BigNumber::operator * (const BigNumber & b) {BigNumber bt=*this; return bt.Mul(b);}BigNumber BigNumber::operator / (int b){BigNumber bt=*this; return bt.Div(b);}BigNumber BigNumber::operator % (int b){BigNumber bt=*this; return bt.Mod(b);}BigNumber & BigNumber::operator += (const BigNumber & b) {return this->Add(b);}BigNumber & BigNumber::operator -= (const BigNumber & b) {return this->Sub(b);}BigNumber & BigNumber::operator *= (const BigNumber & b) {return this->Mul(b);}BigNumber & BigNumber::operator /= (int b){return this->Div(b);}BigNumber & BigNumber::operator %= (int b){return this->Mod(b);}第四章数论算法1.Greatest Common Divisor最大公约数int GCD(int x, int y){int t;while(y > 0) {t = x % y;x = y;y = t;}return x;}2.Prime素数判断bool is_prime(int u){if(u == 0 || u == 1) return false;if(u == 2) return true;if(u%2 == 0) return false;for(int i=3; i <= sqrt(u) ;i+=2)if(u%i==0) return false;return true;}3.Sieve Prime素数筛法const int M = 1000; // M : sizebool mark[M]; // true : prime numbervoid sieve_prime(){memset(mark, true, sizeof(mark));mark[0] = mark[1] = false;for(int i=2; i <= sqrt(M) ;i++) {if(mark[i]) {for(int j=i*i; j < M ;j+=i)mark[j] = false;}}}4.Module Inverse模逆元// ax ≡ 1 (mod n)int Inv(int a, int n){int d, x, y;d = extended_euclid(a, n, x, y);if(d == 1) return (x%n + n) % n;else return -1; // no solution}5.Extended Euclid扩展欧几里德算法//如果GCD(a,b) = d, 则存在x, y, 使d = ax + by// extended_euclid(a, b) = ax + byint extended_euclid(int a, int b, int &x, int &y){int d;if(b == 0) {x = 1; y = 0; return a;}d = extended_euclid(b, a % b, y, x);y -= a / b * x;return d;}6.Modular Linear Equation模线性方程(同余方程) //如果GCD(a, b)不能整除c, 则ax + by = c 没有整数解// ax ≡ b (mod n) n > 0//上式等价于二元一次方程ax – ny = bvoid modular_linear_equation(int a, int b, int n){int d, x, y, x0;d = extended_euclid(a, n, x, y);if( b%d == 0) {x0 = ( x*(b/d) ) % n; // x0 : basic solutionint ans = n;for(int i=0; i < d ;i++) {ans = ( x0 + i*(n/d) ) % n;cout << ans << endl;}}else cout << "no solution" << endl;}7.Chinese Remainder Theorem中国余数定理// x ≡ b[i] (mod w[i]), i∈[1, len-1]// 前提条件w[i] > 0, 且w[]中任意两个数互质int chinese_remainder(int b[], int w[], int len){int i, d, x, y, m, n;x = 0; n = 1;for(i=0; i < len ;i++) n *= w[i];for(i=0; i < len ;i++) {m = n / w[i] ;d = extended_euclid(w[i], m, x, y);x = (x + y*m*b[i]) % n;}return (n + x%n) % n;}第五章图论算法1.最小生成树(Kruscal算法)/**** **** **** **** **** ***** Function Name : 最小生成树(Kruscal算法)* Description : ZJU 1203 Swordfish O(E*LogE)**** **** **** **** **** ****/#include <iostream>#include <algorithm>#include <cstdio>#include <cmath>using namespace std;struct struct_edges{int bv,tv; //bv 起点 tv 终点double w; //权值};struct_edges edges[10100]; //边集struct struct_a{double x;double y;};struct_a arr_xy[101];int point[101],n,e; //n 顶点数, e 边数(注意是无向网络)double sum;int kruscal_f1(int point[], int v){int i = v;while(point[i] > 0) i = point[i];return i;}bool UDlesser(struct_edges a, struct_edges b){return a.w < b.w;}void kruscal() //只需要准备好n,e,递增的边集edges[]即可使用{int v1,v2,i,j;for(i=0; i<n ;i++) point[i]=0;i = j = 0;while(j<n-1 && i<e) {v1 = kruscal_f1(point, edges[i].bv);v2 = kruscal_f1(point, edges[i].tv);if(v1 != v2) {sum += edges[i].w; //注意sum初始为0point[v1]=v2;j++;}i++;}}int main(){int k,i,j;cin>>n;k=0;while(n != 0) {sum=0;k++;for(i=0; i<n ;i++)cin>>arr_xy[i].x>>arr_xy[i].y;e=0;for(i=0; i<n ;i++) //从0开始计数for(j=i+1; j<n ;j++) //注意是无向网络{if(i == j) continue;edges[e].bv=i;edges[e].tv=j;edges[e].w=sqrt((arr_xy[i].x-arr_xy[j].x)*(arr_xy[i].x-arr_xy[j].x)+( arr_xy[i].y-arr_xy[j].y)*(arr_xy[i].y-arr_xy[j].y));e++;}sort(edges,edges+e,UDlesser); //得到一个递增的边集,注意是从0开始计数kruscal();printf("Case #%d:\n",k); //cout<<"Case #"<<k<<":"<<endl;printf("The minimal distance is: %.2f\n",sum); //输出sumcin>>n;if(n != 0) printf("\n");}}2.最小生成树(Prim算法)/**** **** **** **** **** ***** Function Name : 最小生成树(Prim算法)* Description : ZJU 1203 Swordfish O(N^2)**** **** **** **** **** ****/#include <iostream>#include <cmath>#include <cstdio>using namespace std;double sum, arr_list[101][101], min;int i, j, k=0, n;struct struct_a{float x;float y;};struct_a arr_xy[101];struct struct_b{int point;float lowcost;};struct_b closedge[101];void prim(int n) //prim 需要准备:n顶点数 arr_list[][]顶点的邻接矩阵也是从0开始计数{int i,j,k;k=0;for(j=0; j<n ;j++) {if(j != k) {closedge[j].point = k;closedge[j].lowcost = arr_list[k][j];}}closedge[k].lowcost=0;for(i=0; i<n ;i++) {min=10000;for(j=0; j<n ;j++) {if (closedge[j].lowcost != 0 && closedge[j].lowcost < min) {k = j;min = closedge[j].lowcost;}}sum += closedge[k].lowcost; //不要改成sum+=min; sum即为所求值 closedge[k].lowcost = 0;for(j=0; j<n ;j++) {if(arr_list[k][j] < closedge[j].lowcost) {closedge[j].point = k;closedge[j].lowcost = arr_list[k][j];}}}}/*arr_list[][]= Wij 如果Vi, Vj有边0 如果i=j无限大如果没有边*/int main(){cin>>n;while(n != 0) {sum=0;k++;for(i=0; i<n ;i++)cin>>arr_xy[i].x>>arr_xy[i].y;for(i=0; i<n ;i++)for(j=0; j<n ;j++) //得到邻接矩阵arr_list[][]arr_list[i][j]=arr_list[j][i]=sqrt((arr_xy[i].x-arr_xy[j].x)*(arr_xy[i].x-arr_xy[j].x)+(arr_xy[i].y-arr_xy[j].y)*(arr_xy[i].y-arr_xy[j].y));prim(n);cout<<"Case #"<<k<<":"<<endl;printf("The minimal distance is: %.2f\n",sum);cin>>n;if(n!=0) printf("\n");}}3.单源最短路径(Bellman-ford算法)/**** **** **** **** **** ***** Function Name : 单源最短路径(Bellman-ford算法)* Description : 可允许有负权**** **** **** **** **** ****/#include <stdio.h>#define MAX 100#define MAXNUM 1000000typedef struct graphnode{int vexnum; //顶点数int arcnum; //边数int gra[MAX][MAX]; //图}Graph;Graph *G;//arc数组中存储的第一个顶点到其他顶点的最短路径//结果存在dis数组中int dis[MAX];int arc[MAX][MAX];void bellman(Graph *G){int i,j;bool sign;for(i=0; i < G->vexnum ;i++) dis[i]=MAXNUM;dis[1] = 0;sign = true;for(i=1; i < G->vexnum ;i++) {sign = false;for(j=0; j < G->arcnum ;j++) {if(dis[ arc[j][0] ] < MAXNUM&& dis[ arc[j][1] ] > dis[ arc[j][0] ] + G->gra[ arc[j][0] ][ arc[j][1] ]) {dis[ arc[j][1] ]=dis[ arc[j][0] ] + G->gra[ arc[j][0] ][ arc[j][1] ];sign = true;}}}return;}4.单源最短路径(Dijkstra算法)/**** **** **** **** **** ***** Function Name : 单源最短路径 (Dijkstra算法)* Description : 贪心, O(N^2), 不能有负权**** **** **** **** **** ****/int matrix[200][200],n; //matrix[][], 30000表示无限大,即无边.否则为有边,其值为边的权值void Dijkstra(int x,int y) //起点Vx 终点Vy{int i,j,k,path[40000],mark[40000];int min,dist[40000];for(i=1;i<=n;i++) {mark[i] = 0;dist[i] = matrix[x][i];path[i] = x;}mark[x] = 1;do {min=30000;k=0;for(i=1;i<=n;i++)if(mark[i]==0 && dist[i]<min) {min = dist[i];k = i;}if(k) {mark[k] = 1;for(i=1;i<=n;i++)if(matrix[k][i]<30000 && min+matrix[k][i]<dist[i]) {dist[i] = min + matrix[k][i];path[i] = k;}}}while(k);cout<<dist[y]<<endl; //dist[y] 的值就是从Vx 到 Vy 的最短路径值//如果希望得到路径,加入如下代码:do {cout<<k<<"<--";k = path[k];}while(k!=x);cout<<x<<endl;}5.全源最短路径(Folyd算法)/**** **** **** **** **** ***** Function Name : 全源最短路径(Folyd算法)* Description : DP, O(N^3)**** **** **** **** **** ****///初始化//min_graph[i][j]=graph[i][j];//path[i][j]=j;void Floyd(){int i,j,k;for(k=0;k<vertex_number;k++) {for(i=0;i<vertex_number;i++) {for(j=0;j<vertex_number;j++) {if((graph[i][k]==-1) || (graph[k][j]==-1)) continue;if((min_graph[i][j]==-1) || (min_graph[i][j] > graph[i][k]+graph[k][j])) {min_graph[i][j] = graph[i][k]+graph[k][j]; /*最短路径值*/path[i][j] = k; /*最短路径*/}}}}}6.拓扑排序/**** **** **** **** **** ***** Function Name : 拓扑排序**** **** **** **** **** ****///degree[] 每个结点的入度//f[] 每个结点所在的层void Toplogical_sort(){int i,j;bool p=true;top=0;while(p) {p=false;top++;for(i=1;i<=n;i++)if(degree[i]==0) {p=true;f[i]=top;}for(i=1;i<=n;i++)if(f[i]==top) {for(j=1;j<=n;j++)if(map[i][j]) degree[j]--;degree[i]=-1;}}top--;}7.网络预流和最大流int rel[1000][10000]; //全局变量int pre[1000];//计算网络流//如果是二分图的匹配, 可以先对其进行网络预流以简化后续的查找int pre_flow(int n,vector<int> * v){int ret = 0;int i,j,t,t1;for(i = 0 ; i < v[0].size() ; i++){t = v[0][i]; //t是与节点0相邻接的点for(j = 0 ; j < v[t].size() ; j++){t1 = v[t][j]; //与t相邻接的点if(rel[t1][n - 1] > 0){ret++;rel[0][t]--, rel[t][0]++;rel[t][t1]--, rel[t1][t]++;rel[t1][n - 1]--, rel[n - 1][t1]++;break;}}}return ret;}/*网络中求最大流参数含义: n代表网络中节点数,第0节点为源点, 第n-1节点为汇点rel是个二维数组, rel[i][j]代表从节点i到节点j的流量v[]是一个节点数组, v[i]包含与节点i相邻接的所有节点返回值: 最大流量*/int max_flow(int n,vector<int> * v){int ret = 0,i;int t,t1,tm;queue<int> q;const int Infinite = 2000000000;while(1){for(t = 0 ; t < n ; t++) pre[t] = -1;while(!q.empty()) q.pop();q.push(0);while(!q.empty()){ //find a augmenting path using breath-first searcht = q.front();q.pop();if(t == n - 1) break; //到达汇点for(i = 0 ; i < v[t].size() ; i++){ //对于t相邻接的所有点查找可行路径 t1 = v[t][i];if(rel[t][t1] > 0 && pre[t1] == -1){pre[t1] = t;q.push(t1);}}}if(q.empty() && t != n - 1) break;tm = Infinite; //此处寻找路径最小值在二分图中可省略while(t != 0){ //find the minimal num in the patht1 = pre[t];if(rel[t1][t] < tm) tm = rel[t1][t];t = t1;}// tm = 1; //二分图中t = n - 1;while(t != 0){ //change the relationt1 = pre[t];rel[t1][t] -= tm;rel[t][t1] += tm;t = t1;}ret += tm;}return ret;}8.网络最小费用最大流/**** **** **** **** **** ****网络中最小费用最大流参数含义: np代表网络中的总节点数, v是网络节点的邻接表cost为最后求得的最小费用, mf为求得的最大流算法: 初始最小费用及最大流均为0,不断寻找可增广路增广路对应的单位费用最小并且可流修改残留网络及cost,mf. 直到无可增广路为止。

个人整理 ACM 模板

个人整理 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() {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() {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) swap(big, small);int temp;while (small != 0){ // 辗转相除法if (small > big) swap(big, small); temp = big % small;big = small;small = temp;}return(big);}5.LCM/*|辗转相除法||欧几里得算法||求最小公倍数||16/11/05ztx|*/int gcd(int big, int small){if (small > big) swap(big, small);int temp;while (small != 0){ // 辗转相除法if (small > big) swap(big, 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++) { // 输出的是满足移动条件所有全排列swap(list[k], list[i]);Pern(list, k + 1, n);swap(list[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常用算法介绍及实用模板

河南大学ACM常用算法介绍及模板河南大学计算机与信息工程学院1一、数学问题 (7)1. 精度计算——大数阶乘 (7)2.精度计算——乘法(大数乘小数)....................................................... 错误!未定义书签。

3.精度计算——乘法(大数乘大数) (8)4.精度计算——加法 (10)5.精度计算——减法 (11)6.精度计算——除法约分 (13)7.任意进制转换 (19)8.最大公约数、最小公倍数 (21)9.组合序列 (22)10.Ronberg算法计算积分 (25)11.行列式计算 (26)12.求排列组合数 (27)二、计算几何 (27)1.叉乘法求任意多边形面积 (28)2.求三角形面积 (29)3.求多边形重心 (30)4.两矢量间角度 (31)5.两点距离(2D、3D) (32)6.射向法判断点是否在多边形内部 (33)7.判断点是否在线段上 (35)29.判断线段与直线是否相交 (39)10.点到线段最短距离 (40)11.求两直线的交点 (42)12.判断一个封闭图形是凹集还是凸集 (43)13.Graham扫描法寻找凸包 (43)三、数论 (50)1.x的二进制长度 (50)2.返回x的二进制表示中从低到高的第i位 (51)3.模取幂运算(反复平方法求数的幂) (51)4.求解模线性方程 (54)5.求解模线性方程组(中国余数定理) (56)6.筛法素数产生器 (58)7.判断一个数是否素数 (61)8.初等数论里的欧拉公式: (61)9.数的分解 (65)10.关于数的阶乘 (67)11.母函数 (69)四、图论 (78)1. 深度优先搜索 (82)2. 边分类算法 (84)3. 连通性 (85)35. 无向图的割顶和桥 (93)6. 欧拉图 (99)1)消圈法(逐步插入回路法) (100)2)Fleury算法(能不走桥就不走桥): (104)7.最小生成树 (114)1).Prim算法(邻接矩阵,无优化): (114)2).Prim算法(邻接表+Heap优先队列优化): (116)3) Kruskal算法: (124)8.Dijkstra算法求单源最短路径 (128)1).邻接矩阵,无优化 (128)2).邻接链表,用优先队列(STL)优化 (133)9.Bellman-ford算法求单源最短路径 (138)10.Floyd-Warshall算法求每对节点间最短路径 (141)五、最大流 (143)1.最大流算法(Ford-Fulkerson) (143)2.最大二分匹配(最大流算法) (146)3.最大二分匹配(匈牙利算法) (150)4.最佳二分匹配(KM算法) (152)5.最小路径覆盖(最大流算法) (159)6.最小路径覆盖(匈牙利算法) (163)7. 关于匹配 (166)41.快速排序 (167)2.希尔排序 (168)3.选择法排序 (170)4.二分查找 (171)七.数据结构 (173)1. 并查集 (173)2. 串的匹配(KMP算法): (182)3. 字典树(字符串的储存与查找): (185)4. 二叉堆(用二叉堆排序及构建优先队列) (189)5. 二叉查找树(可作为优先队列) (194)6. 红黑树 (200)7. 树状数组 (215)1).一维数组代码(子段和): (216)2).二维数组代码(子阵和): (218)8. 线段树 (221)9. 归并树 (228)10. 后缀数组(Suffix Array) (233)八.博弈问题例题分析 (239)例1.POJ1740 A New Stone Game (240)例2.MIPT100 Nim Game -- who is the winner? (242)例3.POJ1704 Georgia and Bob (243)5例4的另种解法: (246)九.其它算法 (246)1. LCS算法 (249)2. 背包问题 (251)3. 回溯法 (256)4. RMQ问题的ST算法 (259)5. 最近公共祖先(LCA)问题 (263)1).RMQ求法 (264)2).Tarjan的脱机(离线)算法 (264)十.杂谈 (280)1.国际象棋 (280)2.STL常用结构简单用法 (280)3.图的度序列 (286)6一、数学问题1. 精度计算——大数阶乘返回值:阶乘结果的位数注意:本程序直接输出n!的结果,需要返回结果请保留long a[] 需要头文件:cmath源程序: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;7if(c>0){m++;a[m]=c;}}w=m*4+(int)log10((double)a[m])+1;//阶乘的位数printf("%ld",a[m]);for(i=m-1;i>=0;i--)printf("%4.4ld",a[i]);printf("\n");return w;}2.精度计算——乘法(大数乘大数)#include<iostream>#include<sstream>using namespace std;string muling(string s1,string s2){8for(int n2=s2.length()-1;n2>=0;n2--)if(s2[n2])for(int n1=s1.length()-1,n=n2+s1.length();n1>=0;--n1,--n){int temp=(s1[n1]-'0')*(s2[n2]-'0');cheng[n-1]=char(cheng[n-1]+(cheng[n]+temp-'0')/10);cheng[n]=char((cheng[n]+temp-'0')%10+'0');}int loc=cheng.find_first_not_of('0');if(loc==-1)return"0";return cheng.substr(loc);}int main(){string s1,s2;cin>>s1>>s2;cout<<muling(s1,s2)<<endl;return 0;}9#include<sstream>#include<iostream>using namespace std;string sum(string s1,string s2){if(s1.length()<s2.length()){string temp=s1;s1=s2;s2=temp;}for(int n1=s1.length()-1,n2=s2.length ()-1;n1>=0;n1--,n2--) {s1[n1]=char(s1[n1]+(n2>=0?s2[n2]-'0':0));if(s1[n1]-'0'>=10){s1[n1]=char((s1[n1]-'0')%10+'0');if(n1)s1[n1-1]++; //想想为什么?如果不是十进制呢?elses1='1'+s1;}return s1;}int main(){for(string s1,s2;cin>>s1>>s2;) cout<<sum(s1,s2)<<endl; return 0;}4.精度计算——减法#include<sstream>#include<iostream>using namespace std;bool compare(string s1,string s2) {if(s1.length()<s2.length())return true;if(s1.length()==s2.length()){if(s1[i]<s2[i])return true;}return false;}//========================================== string subing(string s1,string s2){bool sign=0;if(s1==s2)return "0";//所以有0-0结果仍正确!if(compare(s1,s2)){string temp=s1;s1=s2;s2=temp;sign=1;}for(int n1=s1.length()-1,n2=s2.length ()-1;n1>=0;n1--,n2--){s1[n1]=char(s1[n1]-(n2>=0?s2[n2]-'0':0));{s1[n1]+=10;s1[n1-1]--;}}if(sign)return '-'+s1.substr(s1.find_first_not_of('0'));return s1.substr(s1.find_first_not_of('0'));}//==================================================== =======int main(){for(string s1,s2;cin>>s1>>s2;)cout<<subing(s1,s2)<<endl;return 0;}5.精度计算——除法约分#include<iostream>#include<sstream>//================================ typedef struct Data{string s1,s2;}Data;//两正的大数比较大小前者大返回1 相等返回0后者大返回-1 int MoreThan(string s1,string s2){if(s1.length()>s2.length())return 1;if(s1.length()<s2.length())return -1;int i;for(i=0;i<s1.length();i++){if(s1[i] != s2[i]){if(s1[i]>s2[i])return 1;elsereturn -1;}return 0;}//=============大数减法==============string OpsitionSub(string s1,string s2){。

ACM模板

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(五篇范例)

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算法

ACM算法

ACM要学那些算法初期:一.基本算法:(1)枚举. (poj1753,poj2965)(2)贪心(poj1328,poj2109,poj2586)(3)递归和分治法.(4)递推.(5)构造法.(poj3295)(6)模拟法.(poj1068,poj2632,poj1573,poj2993,poj2996)二.图算法:(1)图的深度优先遍历和广度优先遍历.(2)最短路径算法(dijkstra,bellman-ford,floyd,heap+dijkstra)(poj1860,poj3259,poj1062,poj2253,poj1125,poj2240)(3)最小生成树算法(prim,kruskal)(poj1789,poj2485,poj1258,poj3026)(4)拓扑排序(poj1094)(5)二分图的最大匹配(匈牙利算法) (poj3041,poj3020)(6)最大流的增广路算法(KM算法). (poj1459,poj3436)三.数据结构.(1)串(poj1035,poj3080,poj1936)(2)排序(快排、归并排(与逆序数有关)、堆排) (poj2388,poj2299)(3)简单并查集的应用.(4)哈希表和二分查找等高效查找法(数的Hash,串的Hash)(poj3349,poj3274,POJ2151,poj1840,poj2002,poj2503)(5)哈夫曼树(poj3253)(6)堆(7)trie树(静态建树、动态建树) (poj2513)四.简单搜索(1)深度优先搜索(poj2488,poj3083,poj3009,poj1321,poj2251)(2)广度优先搜索(poj3278,poj1426,poj3126,poj3087.poj3414)(3)简单搜索技巧和剪枝(poj2531,poj1416,poj2676,1129)五.动态规划(1)背包问题. (poj1837,poj1276)(2)型如下表的简单DP(可参考lrj的书page149):1.E[j]=opt{D[i]+w(i,j)} (poj3267,poj1836,poj1260,poj2533)2.E[i,j]=opt{D[i-1,j]+xi,D[i,j-1]+yj,D[i-1][j-1]+zij} (最长公共子序列)(poj3176,poj1080,poj1159)3.C[i,j]=w[i,j]+opt{C[i,k-1]+C[k,j]}.(最优二分检索树问题)六.数学(1)组合数学:1.加法原理和乘法原理.2.排列组合.3.递推关系.(POJ3252,poj1850,poj1019,poj1942)(2)数论.1.素数与整除问题2.进制位.3.同余模运算.(poj2635, poj3292,poj1845,poj2115)(3)计算方法.1. 二分法求解单调函数相关知识。

ACM比赛用的简单模板

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. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
void init()
{
memset(head,-1,sizeof(head));
tot=0;
memset(vis,0,sizeof(vis));
}
void add(inHale Waihona Puke x,int y)//有向图{
to[tot]=y,nxt[tot]=head[x],head[x]=tot++;
{
memset(head,-1,sizeof(head));
memset(d,0,sizeof(d));
memset(vis,0,sizeof(vis));
tot=0;
ans.clear();
}
void add(int x,int y,int z)//加双向边,如果是有向图则只加单向边
{
d[x]++,to[tot]=y,id[tot]=z,nxt[tot]=head[x],head[x]=tot++;
*/
const int N=10010;
const int M=100010;
//链式前向星
int head[N],to[M<<1],nxt[M<<1];
int tot;
int dfn[N],low[N],tm;
int belong[N];//每个点属于哪个边双
int bridge[M];//是否是桥
add(x,y,i);
}
int flag=0;//是否存在欧拉回路
for(int i=1; i<=n; i++)
if(d[i]&1) flag=1; //有奇数度的点,不存在欧拉回路
//如果是欧拉路径则修改相应判断条件
for(int i=1; i<=n; i++)
{
if(d[i]>0)//如果是欧拉路径,则从满足条件的起点开始dfs
for(int i=1; i<=n; i++)
if(!belong[i]) dfs(i,++num);
return 0;
}
3.点双连通分量
/*
求无向图的割点和每个点所属的点双连通分量,复杂度O(M)
无向图中去掉任意一个点不改变连通性称为点双联通
割点可能属于多个点双
在dfs树中,根节点多余1个儿子则为割点,其余点如果在不经过dfs到自己的那条树边的情况下,不能回到比自己高的点,则为割点
*/
const int N=10010;
const int M=100010;
//链式前向星
int head[N],to[M<<1],nxt[M<<1];
int tot;
int dfn[N],low[N],tm;
int S[N],top;//用栈存储dfs路径上的结点
int belong[N];//每个点属于哪个强连通分量
if(dfn[x]<=low[y])
{
if(fa||son>1) cut[x]=1;//x是多余一个儿子的根节点或回不到更高的点,则x是割点
num++;
belong[num].clear();
while(1)
{
cut[S[top]]=1;
belong[num].push_back(S[top]);
if(S[top--]==y) break;
dfs(to[i],y);
}
}
int n,m,x,y;
int main()
{
scanf("%d%d",&n,&m);
init();
for(int i=1; i<=m; i++)
{
scanf("%d%d",&x,&y);
add(x,y);
}
for(int i=1; i<=n; i++)
if(!dfn[i]) tarjan(i,-1);
add(x,y);
}
for(int i=1; i<=n; i++)
if(!dfn[i]) tarjan(i,0);
return 0;
}
4.强连通分量
/*
求有向图每个点所属的强连通分量,复杂度O(M)
有向图中任意两点都相互可达为强连通
在dfs树中,点如果在不经过dfs到自己的那条树边的情况下,恰好能回到自己,则为对应强连通分量的最高点,其余点保存在栈中
}
else if(low[x]>dfn[y]) low[x]=dfn[y];
}
if(dfn[x]==low[x])//x是强连通分量的最高点
{
num++;
while(1)
{
belong[S[top]]=num;
if(S[top--]==x) break;
}
}
}
int n,m,x,y;
int main()
{
dfn[x]=low[x]=++tm;
S[++top]=x;
for(int i=head[x]; i>=0; i=nxt[i])
{
int y=to[i];
if(y==fa) continue;
if(!dfn[y])
{
if(!fa) son++;
tarjan(y,x);
if(low[x]>low[y]) low[x]=low[y];//low记录能回到的最高点
1.欧拉回路
/*
判断是否存在欧拉回路,如果存在则打印回路,复杂度O(M)
无向连通图存在欧拉回路:每个点的度为偶数
无向连通图存在欧拉路径:两个点的度为奇数
有向连通图存在欧拉回路:每个点的入度等于出度
有向连通图存在欧拉路径:一个点入度等于出度+1,一个点出度等于入度+1,其余点入度等于出度
构造回路的方法:每次寻找一条简单回路,并将新回路插入到老回路中
for(int i=head[x]; i>=0; i=nxt[i])
{
if((i^1)==fa) continue;
if(!dfn[to[i]])
{
tarjan(to[i],i);
if(low[x]>low[to[i]]) low[x]=low[to[i]];//low记录能回到的最高点
}
else low[x]=min(low[x],dfn[to[i]]);
int num;//强连通个数
void init()
{
memset(head,-1,sizeof(head));
tot=0;
memset(dfn,0,sizeof(dfn));
tm=0;
num=0;
top=0;
}
void add(int x,int y)//有向图
{
to[tot]=y,nxt[tot]=head[x],head[x]=tot++;
num=0;
son=0;
top=0;
}
void add(int x,int y)//无向图
{
to[tot]=y,nxt[tot]=head[x],head[x]=tot++;
to[tot]=x,nxt[tot]=head[y],head[y]=tot++;
}
void tarjan(int x,int fa)//重边对点双没有影响,fa为父节点即可
}
belong[num].push_back(x);
}
}
else if(low[x]>dfn[y]) low[x]=dfn[y];
}
}
int n,m,x,y;
int main()
{
scanf("%d%d",&n,&m);
init();
for(int i=1; i<=m; i++)
{
scanf("%d%d",&x,&y);
{
dfs(i);
break;
}
}
for(int i=0; i<2*m; i++)
if(!vis[i]) flag=1;//有多个非孤立点的联通块,不存在欧拉回路
if(flag) printf("NO\n");
else
{
printf("YES\n");
for(int i=m-1; i>=0; i--) printf("%d%c",ans[i],i?' ':'\n');//ans按逆序存储
int num;//边双个数
void init()
{
memset(head,-1,sizeof(head));
tot=0;
memset(bridge,0,sizeof(bridge));
memset(belong,0,sizeof(belong));
tm=0;
num=0;
}
void add(int x,int y)//无向图
{
to[tot]=y,nxt[tot]=head[x],head[x]=tot++;
to[tot]=x,nxt[tot]=head[y],head[y]=tot++;
}
void tarjan(int x,int fa)//fa记录dfs到x的树边,用边而不用父节点是为了处理重边
相关文档
最新文档