ACM必做50题——快速查找
acm数学竞赛试题
acm数学竞赛试题
ACM数学竞赛试题通常涉及各种数学领域,包括但不限于代数、几何、概率统计和组合数学等。
以下是一些经典的ACM数学竞赛试题:
1. 平面上n个点的k距离和最小值问题:给定平面上n个点,对于每个点,计算它到其他所有点的距离,然后求出这些距离中的k个最小值。
问题是:如何有效地计算这k个最小值?
2.最长公共子序列问题:给定两个序列,找出它们的最长公共子序列。
例如,对于序列
A = [1, 2, 3, 4] 和
B = [2, 3, 4, 5],最长公共子序列是[2, 3, 4]。
3. 凸包问题:给定平面上的一组点,找到一个最小的凸多边形,使得这个多边形能够包含这组点中的所有点。
4. 最短路问题:给定一个有向图,其中每条边都有一个非负的权重,找出图中任意两点之间的最短路径。
5. 子集和问题:给定一个正整数数组和一个目标值,判断数组中是否存在和为目标值的两个非空子集。
例如,给定数组[1, 2, 3, 4] 和目标值7,判断是否存在两个子集,它们的和分别为7。
以上只是ACM数学竞赛试题的一部分,实际上还有更多涉及数学各个领域的题目。
要提高解决这类问题的能力,需要不断练习和研究。
acm编程比赛入门题目集
最少钱币数:【问题描述】这是一个古老而又经典的问题。
用给定的几种钱币凑成某个钱数,一般而言有多种方式。
例如:给定了6种钱币面值为2、5、10、20、50、100,用来凑15元,可以用5个2元、1个5元,或者3个5元,或者1个5元、1个10元,等等。
显然,最少需要2个钱币才能凑成15元。
你的任务就是,给定若干个互不相同的钱币面值,编程计算,最少需要多少个钱币才能凑成某个给出的钱数。
【要求】【数据输入】输入可以有多个测试用例。
每个测试用例的第一行是待凑的钱数值M(1 <= M <= 2000,整数),接着的一行中,第一个整数K(1 <= K <= 10)表示币种个数,随后是K 个互不相同的钱币面值Ki(1 <= Ki <= 1000)。
输入M=0时结束。
【数据输出】每个测试用例输出一行,即凑成钱数值M最少需要的钱币个数。
如果凑钱失败,输出“Impossible”。
你可以假设,每种待凑钱币的数量是无限多的。
【样例输入】156 2 5 10 20 50 10011 2【样例输出】2Impossible/***************** 2010年5月19日*****************/#include<iostream>#include<string>using namespace std;int m[1000];int M;int p;int check() { //找出最少钱币数,并返回其值int b,c,d=0;int p=0;int i,j;int s[10];cin>>b;for( i=1;i<=b;i++)cin>>s[i];/*冒泡排序排出从大到小的钱币面额顺序*/ for( i=1;i<=b;i++)for(j=1;j<=b-i;j++)if(s[j]>s[j+1]){c=s[j];s[j]=s[j+1];s[j+1]=c;}/*尝试用最大面额的钱币开始凑某个价位,并尽量凑足此价位;如果剩余的价位差额可以用剩余的钱币面额凑到,且钱币用量最少,则凑到的原价位所需的钱币用量最少*/for( i=b;i>0;i--){while(M-s[i]>=0){M-=s[i];d++;}}if(M<=0)return d;elsereturn 0;}int main() {int q;/*用循环来解决多次输入样例*/do {cin>>M; q=M;if(q==0)break;p++;m[p]=check();//用数组存储凑成M的最少钱币数 }while(q>0);for(int j=1;j<=p;j++){if(m[j]==0)cout<<"Impossible"<<endl;elsecout<<m[j]<<endl;}return 0;}Feli 的生日礼物【问题描述】Felicia 的生日是11月1日(和Kitty是同一天生的哦)。
acm常用板子题
acm常用板子题
ACM常用模板题包括但不限于:
字符串操作:如字符串匹配、字符串排序、字符串还原等题目,需要熟练掌握字符串的基本操作和常用算法。
数组操作:如数组排序、数组查找、数组分割等题目,需要熟练掌握数组的基本操作和常用算法。
树形结构:如二叉树、AVL树、红黑树等题目,需要熟练掌握树形结构的基本操作和常用算法。
图论算法:如最短路径、最小生成树、拓扑排序等题目,需要熟练掌握图论算法的基本操作和常用算法。
动态规划:如背包问题、最长公共子序列、最长递增子序列等题目,需要熟练掌握动态规划的基本操作和常用算法。
搜索算法:如深度优先搜索、广度优先搜索等题目,需要熟练掌握搜索算法的基本操作和常用算法。
数据结构:如哈希表、并查集、线段树等题目,需要熟练掌握数据结构的基本操作和常用算法。
以上是一些常见的ACM模板题,当然还有很多其他的题目类型。
要提高自己的ACM水平,需要多做题、多思考、多总结,不断拓宽自己的算法和数据结构知识面。
ACM搜索题(新)
同时,要求: p*q<=m<=100000 所以无论如何质数都不能超过10000。(事实上, 不会超过9091)
搜索时的技巧:
搜索顺序很重要。建议从大往小搜 ( num:质数的个数 )
注意剪枝:
If ( a[j]>m || a[j]*a[i]>m || ( (double)a[i]/a[j])<s )
示例如下:
1
2
3
4
5
6
7
以上二叉树的层次遍历序列是:?? 1、2、 3、 4、5、6、7
三、广度优先搜索
基本思想:从初始状态S开始,利用规则,
生成所有可能的状态。构成树的下一层节 点,检查是否出现目标状态G,若未出现, 就对该层所有状态节点,分别顺序利用规 则。生成再下一层的所有状态节点,对这 一层的所有状态节点检查是否出现G,若未 出现,继续按上面思想生成再下一层的所 有状态节点,这样一层一层往下展开。直 到出现目标状态为止。
HDOJ_1010 Tempter of the Bone
Sample Input
445 S.X. ..X. ..XD .... 345 S.X. ..X. ...D 000
Sample
Output
NO YES
要点分析:
典型的迷宫搜索,做出该题将具有里程碑 式的意义! 每个block只能走一次 要求恰好某个给定的时间到达出口
搜索题
2014-3-5
1
搜索题特点分析:
题意容易理解 算法相对固定 编程有路可循 竞赛必备知识
引言
“算法中最基本和常用的是搜索,主要是回溯和 分支限界法的使用。这里要说的是,有些初学者 在学习这些搜索基本算法是不太注意剪枝,这是 十分不可取的,因为所有搜索的题目给你的测试 用例都不会有很大的规模,你往往察觉不出程序 运行的时间问题,但是真正的测试数据一定能过 滤出那些没有剪枝的算法。实际上参赛选手基本 上都会使用常用的搜索算法,题目的区分度往往 就是建立在诸如剪枝之类的优化上了。 ”
acm竞赛试题及答案
acm竞赛试题及答案ACM(Association for Computing Machinery)竞赛是一项全球性计算机科学竞赛,旨在锻炼参赛者的问题解决能力和编程技巧。
每年都有数千名来自不同学校的学生参加这一挑战。
本文将提供一些最近的ACM竞赛试题以及相应的答案,帮助读者了解和学习竞赛题目的类型和解题思路。
1. 问题描述给定一个由N个整数组成的数组A,请编写一个程序,找出数组中两个不同元素的差的最小值。
2. 输入格式- 第一行包含一个整数N,表示数组A的长度。
- 第二行包含N个以空格分隔的整数,表示数组A中的元素。
3. 输出格式输出一个整数,表示数组中两个不同元素的差的最小值。
4. 示例输入:51 52 9 12输出:15. 解题思路该问题可以通过对数组进行排序,并比较相邻两个数的差值来求解。
首先,将数组A进行升序排序。
然后,遍历排序后的数组,依次计算相邻两个数的差值,并记录其中的最小值。
最后,返回这个最小差值即可。
6. 代码实现```pythondef min_difference(nums):nums.sort() # 对数组进行升序排序min_diff = float('inf') # 初始化最小差值为正无穷大for i in range(len(nums)-1):diff = abs(nums[i] - nums[i+1]) # 计算相邻两个数的差值min_diff = min(min_diff, diff) # 更新最小差值return min_diff# 输入处理N = int(input())A = list(map(int, input().split()))# 调用函数并输出结果result = min_difference(A)print(result)```7. 答案解析对给定的数组进行排序后,遍历数组计算相邻两个数的差值,并记录其中的最小值。
上述代码中,首先将数组A进行升序排序,然后使用一个变量`min_diff`来记录最小差值。
acm试题及答案python
acm试题及答案pythonACM试题及答案(Python)1. 问题描述:给定一个整数数组,请编写一个Python函数,找出数组中第二大的数。
2. 输入格式:一个包含整数的列表。
3. 输出格式:一个整数,表示数组中第二大的数。
4. 示例:- 输入:[10, 5, 8, 20, 15]- 输出:155. 答案:```pythondef find_second_max(nums):first_max = float('-inf')second_max = float('-inf')for num in nums:if num > first_max:second_max = first_maxfirst_max = numelif num > second_max and num != first_max:second_max = numreturn second_max if second_max != float('-inf') else None# 示例测试nums = [10, 5, 8, 20, 15]print(find_second_max(nums)) # 输出应为15```6. 分析:此题要求找出数组中第二大的数。
我们可以通过遍历数组,使用两个变量分别记录当前找到的最大值和第二大值。
在遍历过程中,如果当前元素比第一大的元素大,则更新第二大的元素为当前第一大的元素,并将当前元素设为第一大的元素。
如果当前元素小于第一大的元素但大于第二大的元素,则更新第二大的元素。
最后返回第二大的元素。
7. 注意:如果数组中只有一个元素或所有元素都相等,则返回`None`。
-【精品资料】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.括号化问题。
北大 poj acm题目推荐50题
-北大poj acm题目推荐50题POJ == 北京大学ACM在线评测系统/JudgeOnline1. 标记难和稍难的题目大家可以看看,思考一下,不做要求,当然有能力的同学可以直接切掉。
2. 标记为A and B 的题目是比较相似的题目,建议大家两个一起做,可以对比总结,且二者算作一个题目。
3. 列表中大约有70个题目。
大家选做其中的50道,且每类题目有最低数量限制。
4. 这里不少题目在BUPT ACM FTP 上面都有代码,请大家合理利用资源。
5. 50个题目要求每个题目都要写总结,养成良好的习惯。
6. 这50道题的规定是我们的建议,如果大家有自己的想法请与我们Email 联系。
7. 建议使用C++ 的同学在POJ 上用G++ 提交。
8. 形成自己编写代码的风格,至少看上去美观,思路清晰(好的代码可以很清楚反映出解题思路)。
9. 这个列表的目的在于让大家对各个方面的算法有个了解,也许要求有些苛刻,教条,请大家谅解,这些是我们这些年的经验总结,所以也请大家尊重我们的劳动成果。
10. 提交要求:一个总文件夹名为bupt0xx (即你的比赛帐号), 这个文件夹内有各个题目类别的子目录(文件夹),将相应的解题报告放入对应类别的文件夹。
在本学期期末,小学期开始前,将该文件夹的压缩包发至buptacm@。
对于每个题目只要求一个POJxxxx.cpp 或POJxxxx.java (xxxx表示POJ该题题号) 的文件,注意不要加入整个project 。
11. 如果有同学很早做完了要求的题目,请尽快和我们联系,我们将指导下一步的训练。
下面是一个解题报告的范例:例如:POJ1000.cpp//考查点:会不会编程序。
//思路:此题要求输入两个数,输出两个数的和,我用scanf 和printf。
//提交情况:Wrong Answer 1次,忘了写printf()。
Compile Error 2次,选错了语言,由于C++ 和G++ 在iostream.h 的不用引用方法;少一个大括号。
acm大赛历年程序题
acm大赛历年程序题
ACM大赛是一项计算机竞赛,每年都会发布一系列的程序题供
参赛者解答。
这些题目涵盖了各个计算机科学领域的知识,包括数
据结构、算法、图论、动态规划、数学等等。
以下是一些历年ACM
大赛的程序题的例子:
1. 最短路径问题,给定一个有向带权图,求两个节点之间的最
短路径。
可以使用Dijkstra算法或者Floyd-Warshall算法来解决。
2. 字符串处理问题,给定一个字符串,要求对其进行特定的处理,比如反转、删除重复字符等。
可以使用字符串操作和遍历来解决。
3. 数组操作问题,给定一个数组,要求对其进行特定的操作,
比如排序、查找最大/最小值、计算数组的平均值等。
可以使用排序
算法、查找算法和遍历来解决。
4. 动态规划问题,给定一个问题和一组限制条件,要求找到满
足条件的最优解。
可以使用动态规划的思想,将问题拆分成子问题
并逐步求解。
5. 图论问题,给定一个图,要求对其进行特定的操作,比如查找连通分量、判断是否存在环等。
可以使用图的遍历和深度优先搜索或广度优先搜索来解决。
6. 数学问题,给定一个数学问题,要求求解或验证某个数学定理或公式。
可以使用数学运算和推导来解决。
这些只是一小部分例子,ACM大赛的题目类型非常多样化,每年都会有新的题目发布。
参赛者需要具备扎实的计算机科学基础知识和良好的编程能力,才能在规定时间内解决这些问题。
acm数学竞赛试题及答案
acm数学竞赛试题及答案# 题目一:数列问题问题描述:给定一个数列 \( a_1, a_2, a_3, \ldots, a_n \),数列中每个元素都是正整数,且满足 \( a_i = a_{i-1} + a_{i-2} \) 对于所有\( i \geq 3 \)。
如果 \( a_1 = 1 \) 且 \( a_2 = 1 \),请找出数列的第 \( n \) 项。
解答:根据题意,这是一个斐波那契数列。
第 \( n \) 项的值可以通过递归关系计算得出。
对于 \( n \) 的值,可以使用以下递归公式:\[ a_n = a_{n-1} + a_{n-2} \]其中,\( a_1 = 1 \) 和 \( a_2 = 1 \)。
因此,数列的前几项为 1, 1, 2, 3, 5, 8, 13, 21, ...。
对于任意的 \( n \),可以通过递归或动态规划方法计算出 \( a_n \)。
# 题目二:组合问题问题描述:从 \( n \) 个不同的元素中选择 \( k \) 个元素的所有可能组合的个数是多少?解答:这个问题可以通过组合数学中的二项式系数来解决。
从 \( n \) 个不同元素中选择 \( k \) 个元素的组合数 \( C(n, k) \) 可以用以下公式计算:\[ C(n, k) = \frac{n!}{k!(n-k)!} \]其中,\( n! \) 表示 \( n \) 的阶乘。
# 题目三:几何问题问题描述:在一个直角坐标系中,给定三个点 \( A(x_1, y_1) \),\( B(x_2, y_2) \) 和 \( C(x_3, y_3) \)。
如果 \( \overrightarrow{AB} \) 和 \( \overrightarrow{AC} \) 是垂直的,求证 \( A \) 是直角三角形 \( ABC \) 的直角顶点。
解答:如果 \( \overrightarrow{AB} \) 和 \( \overrightarrow{AC} \) 垂直,那么它们的数量积(点积)应该为零。
ACM必做50题的解题-模拟
}
return 1;
}
int main(){
int i,j,n;
char c;
scanf("%d",&n);
while(n--){
for(i=1; i<=3; i++)
scanf("%s %s %s",left[i],right[i],result[i]);
for(c='A'; c<='L'; c++){
1)选择合适的算法
对于每一枚硬币x逐个试探:
x比真币轻的猜测是否成立?猜测成立则进行输出。
x比真币重的猜测是否成立?猜测成立则进行输出。
2)选择合适的数据结构
以字符串数组存储称量的结果。每次称量时,天平左右最多有6枚硬币。因此,字
符串的长度需要为7,最后一位存储字符串的结束符’\0’,便于程序代码中使用字符串
{
int t,n;
cin>>t;
while(t--){
cin>>n;
int x,y;
int cross[SIZE];
memset(cross,0,sizeof(cross));
for(int i=0;i<n;++i){
cin>>x>>y;
int start,end;
if(x>y){
swapnum(x,y);
case 'u': if( strchr(left[i], x) == NULL) return 0;
break;
case 'e': if(strchr(right[i], x) != NULL || strchr(left[i], x) != NULL) return 0;
ACM程序设计竞赛例题
ACM程序设计竞赛例题备战ACM资料习题1. 0-1背包问题在0 / 1背包问题中,需对容量为c 的背包进行装载。
从n 个物品中选取装入背包的物品,每件物品i 的重量为wi ,价值为pi 。
对于可行的背包装载,背包中物品的总重量不能超过背包的容量,最佳装载是指所装入的物品价值最高。
程序如下:#includevoid readdata();void search(int);void checkmax();void printresult();int c=35, n=10; //c:背包容量;n:物品数int w[10], v[10]; //w[i]、v[i]:第i件物品的重量和价值int a[10], max; //a数组存放当前解各物品选取情况;max:记录最大价值//a[i]=0表示不选第i件物品,a[i]=1表示选第i件物品int main() {readdata(); //读入数据search(0); //递归搜索printresult();}void search(int m){if(m>=n)checkmax(); //检查当前解是否是可行解,若是则把它的价值与max 比较else{a[m]=0; //不选第m件物品search(m+1); //递归搜索下一件物品a[m]=1; //不选第m件物品search(m+1); //递归搜索下一件物品}}void checkmax(){int i, weight=0, value=0;for(i=0;i<n;i++)< p="">{if(a[i]==1) //如果选取了该物品{weight = weight + w[i]; //累加重量value = value + v[i]; //累加价值}}if(weight<=c) //若为可行解if(value>max) //且价值大于maxmax=value; //替换max}void readdata(){int i;for(i=0;i<n;i++)< p="">scanf("%d%d",&w[i],&v[i]); //读入第i件物品重量和价值}void printresult(){printf("%d",max);}2.装载问题有两艘船,载重量分别是c1、c2,n个集装箱,重量是wi (i=1…n),且所有集装箱的总重量不超过c1+c2。
ACM必做50题的解题-搜索
POJ1011 Sticks 搜索+强剪枝这个题目是不是贪心的,我就是第一次用了贪心,一直W A,相当的悲剧,贪心错误的sample:7 15 11 8 8 8 4 3 2 1,所以大家还是全部搜索。
但是全部搜索必须剪枝,不然肯定是TLE的,而且本体属于强剪枝,少剪了也是TLE。
经典搜索题,果然是到处充斥着剪枝才能过啊,我的代码离剪到极限还差很多题目给出一大堆小棍子的长度,需要把他们拼成几根长度相等的大棍子,求大棍子的最短长度看自己剪枝方法的效果时候,可以添设一个变量来记录递归次数如剪枝4:没有这个剪枝的情况下对以下数据需要40万次递归,而加上这个剪枝后减少到了4万多次对数据:4515 3 2 4 11 1 8 8 8 15 3 2 4 11 1 8 8 8 15 3 2 4 11 1 8 8 8 15 3 2 4 11 1 8 8 8 15 3 2 4 11 1 8 8 8#include <iostream>#include <algorithm>using namespace std;int sticks[65];int used[65];int n,len;bool dfs(int i,int l,int t)//i为当前试取的棍子序号,l为要拼成一根完整的棍子还需要的长度,t初值为所有棍子总长度{if(l==0){t-=len;if(t==0)return true;for(i=0;used[i];++i); //剪枝1:搜索下一根大棍子的时候,找到第一个还没有使用的小棍子开始used[i]=1; //由于排序过,找到的第一根肯定最长,也肯定要使用,所以从下一根开始搜索if(dfs(i+1,len-sticks[i],t))return true;used[i]=0;t+=len;}{for(int j=i;j<n;++j){if(j>0&&(sticks[j]==sticks[j-1]&&!used[j-1])) //剪枝2:前后两根长度相等时,如果前面那根没被使用,也就是由前面那根continue; //开始搜索不到正确结果,那么再从这根开始也肯定搜索不出正确结果,此剪枝威力较大if(!used[j]&&l>=sticks[j]) //剪枝3:最简单的剪枝,要拼成一根大棍子还需要的长度L>=当前小棍子长度,才能选用{l-=sticks[j];used[j]=1;if(dfs(j,l,t))return true;l+=sticks[j];used[j]=0;if(sticks[j]==l) //剪枝4:威力巨大的剪枝,程序要运行到此处说明往下的搜索失败,若本次的小棍长度刚好填满剩下长度,但是后break; //面的搜索失败,则应该返回上一层}}}return false;}bool cmp(const int a, const int b){return a>b;}int main(){while(cin>>n&&n){int sum=0;for(int i=0;i<n;++i){cin>>sticks[i];sum+=sticks[i];used[i]=0;}sort(sticks,sticks+n,cmp); //剪枝5:从大到小排序后可大大减少递归次数bool flag=false;for(len=sticks[0];len<=sum/2;++len) //剪枝6:大棍长度一定是所有小棍长度之和的因数,且最小因数应该不小于小棍中最长的长度{if(sum%len==0){if(dfs(0,len,sum)){flag=true;cout<<len<<endl;break;}}}if(!flag)cout<<sum<<endl;}return 0;}poj 1033 Defragment题意:磁盘整理,按照从第一个文件到最后一个文件的顺序排放,而且每个文件的碎片按原来的顺序放在一起,要求转移的次数最少。
ACM选拔测试题(学生版)
----------------------------精品word 文档 值得下载 值得拥有---------------------------------------------- 1. 座位调整问题问题题目描述:公司办公区里到处摆放着各种各样的零食。
人力资源部的调研发现,员工如果可以在自己喜欢的美食旁边工作,工作效率会大大提高。
因此,公司决定进行一次员工座位的大调整。
调整的方法如下:1 . 首先将办公区按照各种零食的摆放分成 N 个不同的区域。
(例如:可乐区,饼干区,牛奶区等等)。
2 . 每个员工对不同的零食区域有不同的喜好程度(喜好程度度的范围为 1 — 100 的整数, 喜好程度越大表示该员工越希望被调整到相应的零食区域)。
3 . 由于每个零食区域可以容纳的员工数量有限,人力资源部希望找到一个最优的调整方案令到总的喜好程度最大。
数据输入:第一行包含两个整数 N , M ,( 1<=N , M<=300 )。
分别表示 N 个区域和 M 个员工。
第二行是 N 个整数构成的数列 a ,其中 a[i] 表示第 i 个区域可以容纳的员工数, (1<=a[i]<=M , a[1]+a[2]+..+a[N]=M) 。
紧接着是一个 M*N 的矩阵 P , P ( i , j )表示第 i 个员工对第 j 个区域的喜好度。
答案输出:对于每个测试数据,输出可以达到的最大的喜好程度。
测试数据:2. 投资问题问题描述:假设有m 元钱,n 项投资,函数()i f x 表示将x 元投入第i 个项目所产生的效益;问如何分配这m 元钱,使得投资的总效益达到最大?(C/C++程序实现)测试数据:5万元钱,4个项目,效益函数如下表所示测试要求:1. 时间2个小时,用C或C++编写程序;2. 可以携带C语言或C++方面的书;----------------------------精品word文档值得下载值得拥有----------------------------------------------。
acm大学生程序试题及答案
acm大学生程序试题及答案1. 题目:字符串反转描述:给定一个字符串,编写一个函数来将字符串中的字符按相反的顺序重新排列。
输入:一个字符串输出:反转后的字符串答案:```pythondef reverse_string(s):return s[::-1]```2. 题目:寻找最大数描述:给定一个整数数组,找出数组中的最大数。
输入:一个整数数组输出:数组中的最大数答案:```pythondef find_max(nums):return max(nums)```3. 题目:两数之和描述:给定一个整数数组和一个目标值,找出数组中和为目标值的两个数的索引(从1开始计数)。
输入:一个整数数组和一个目标值输出:两个数的索引,如果没有则返回空数组答案:```pythondef two_sum(nums, target):num_to_index = {}for i, num in enumerate(nums):complement = target - numif complement in num_to_index:return [num_to_index[complement] + 1, i + 1] num_to_index[num] = ireturn []```4. 题目:无重复字符的最长子串描述:给定一个字符串,请你找出其中不含有重复字符的最长子串的长度。
输入:一个字符串输出:最长子串的长度答案:```pythondef length_of_longest_substring(s):char_map = {}start = max_length = 0for end in range(len(s)):if s[end] in char_map:start = max(start, char_map[s[end]] + 1)char_map[s[end]] = endmax_length = max(max_length, end - start + 1)return max_length```5. 题目:整数转罗马数字描述:将一个整数转换为罗马数字。
atcoder 经典 思维题
atcoder 经典思维题随着编程竞赛的兴起,来自全球各地的程序员们都在不断挑战各种编程题目,其中atcoder作为日本最有影响力的编程竞赛评台之一,其题目涵盖了各种难度和类型,尤其以经典思维题著称。
本文将介绍一些atcoder上的经典思维题,并共享解题思路,希望能给读者带来启发和帮助。
1. 逆序对逆序对是一种常见的思维题,在atcoder的比赛中也频繁出现。
题目通常要求计算一个数组中逆序对的个数,即满足i < j 且 a[i] > a[j]的数对(i, j)的个数。
解决这类问题的常用方法是归并排序,在归并排序的过程中同时统计逆序对的个数,时间复杂度为O(nlogn)。
2. 快速幂快速幂是另一个经典的思维题,它通常涉及大数的幂运算,要求在较短的时间内得出结果。
解决这类问题的算法是通过二进制分解幂指数,对每一位进行运算,将时间复杂度降低到O(logn)。
3. 贪心算法贪心算法在atcoder的经典思维题中也占据重要地位。
这类问题通常要求在某种限制条件下求最优解,而贪心算法的基本思想是每一步都做出局部最优的选择,最终达到全局最优。
对于这类问题,需要灵活运用数学推导和逻辑思维,找到问题的最优解。
4. 动态规划动态规划是解决复杂问题的利器,也是atcoder上常见的思维题类型。
动态规划的核心思想是将大问题分解成小问题,通过保存子问题的解来避免重复计算,从而大幅度提高计算效率。
对于这类问题,需要掌握动态规划的基本原理和常见的状态转移方程,才能迅速解决难题。
总结atcoder上的经典思维题涵盖了逆序对、快速幂、贪心算法、动态规划等多种类型,解决这些问题需要程序员具备扎实的算法基础和灵活的思维方式。
在日常学习编程和参加编程竞赛的过程中,多多练习这些经典思维题,不断提升自己的算法水平和编程能力。
希望本文介绍的内容能对读者有所帮助,也欢迎大家积极探讨和交流,共同进步。
在atcoder的经典思维题中,逆序对问题是一个常见且具有挑战性的题目。
acm编程例题 参考答案
acm编程例题参考答案ACM编程例题参考答案ACM(Advanced Computer Mathematics)是一种面向计算机科学与技术的竞赛形式,旨在提高参与者的编程技能和解决问题的能力。
ACM编程例题是指在ACM竞赛中出现的一系列编程题目,这些题目涵盖了各种算法和数据结构的应用。
本文将给出一些ACM编程例题的参考答案,希望能够帮助读者更好地理解和掌握这些题目的解法。
一、题目一:最大公约数题目描述:给定两个正整数a和b,求它们的最大公约数。
解题思路:最大公约数可以通过欧几里得算法来求解。
该算法的基本思想是,两个正整数的最大公约数等于其中较小的数和两数之差的最大公约数。
具体的实现可以使用递归或循环的方式。
代码示例:```c++int gcd(int a, int b) {if (b == 0) {return a;}return gcd(b, a % b);}```二、题目二:素数判断题目描述:给定一个正整数n,判断它是否为素数。
解题思路:素数是只能被1和自身整除的正整数。
判断一个数是否为素数可以使用试除法,即从2开始,依次判断n是否能被2到sqrt(n)之间的数整除。
如果存在能整除n的数,则n不是素数;否则,n是素数。
代码示例:```c++bool isPrime(int n) {if (n <= 1) {return false;}for (int i = 2; i * i <= n; i++) {if (n % i == 0) {return false;}}return true;}```三、题目三:字符串反转题目描述:给定一个字符串s,将其反转后输出。
解题思路:字符串反转可以通过将字符串的首尾字符依次交换来实现。
可以使用双指针的方式,一个指针指向字符串的首字符,另一个指针指向字符串的尾字符,然后交换两个指针所指向的字符,并向中间移动,直到两个指针相遇。
代码示例:```c++void reverseString(string& s) {int left = 0;int right = s.length() - 1;while (left < right) {swap(s[left], s[right]);left++;right--;}}```四、题目四:二分查找题目描述:给定一个有序数组和一个目标值,使用二分查找算法在数组中找到目标值的索引,如果目标值不存在,则返回-1。
acm竞赛题库python
acm竞赛题库python
ACM竞赛题库Python版是一个非常有用的资源,可以帮助你准备参加ACM/ICPC等算法竞赛。
以下是一些可能有用的Python库和工具,可以帮助你解决ACM竞赛中的问题:
1.Python标准库:Python标准库包含了许多有用的模块和函数,可以用于解决各种问题,如文件I/O、网络编程、数据库交互等。
2.NumPy和SciPy:这两个库提供了大量的数学函数和算法,可以帮助你处理大规模的数据和进行科学计算。
3.Pandas:Pandas是一个数据分析库,可以帮助你处理数据、清洗数据、进行数据分析和可视化等。
4.Matplotlib和Seaborn:这两个库提供了数据可视化的功能,可以帮助你更好地理解数据和可视化结果。
5.DFS和BFS算法:深度优先搜索(DFS)和广度优先搜索(BFS)是解决图论问题的常用算法。
Python中有许多库可以帮助你实现这两个算法,如NetworkX。
6.动态规划算法:动态规划是一种常用的算法思想,可以帮助你解决许多优化问题。
Python中有许多库可以帮助你实现动态规划算法,如Pymdp。
7.字符串操作库:ACM竞赛中经常涉及到字符串操作的问题,Python中有许多库可以帮助你进行字符串操作,如re和string。
8.集合论算法:集合论是一种常用的数学工具,可以帮助你解决许多问题。
Python中有许多库可以帮助你实现集合论算法,如SymPy。
以上是一些可能有用的Python库和工具,当然还有很多其他的库和工具可以帮助你解决ACM竞赛中的问题。
最重要的是掌握基本的算法和数据结构,并能够灵活运用这些工具来解决实际问题。
acm试题及答案
acm试题及答案ACM试题及答案试题 1: 给定一个整数数组,请找出数组中第二大的数。
答案:1. 对数组进行排序。
2. 数组排序后,倒数第二个元素即为第二大的数。
试题 2: 编写一个函数,计算给定字符串中字符出现的次数。
答案:```pythondef count_characters(s):count_dict = {}for char in s:if char in count_dict:count_dict[char] += 1else:count_dict[char] = 1return count_dict```试题 3: 判断一个数是否为素数。
答案:1. 如果数小于2,则不是素数。
2. 从2开始到该数的平方根,检查是否有因数。
3. 如果没有因数,则该数是素数。
试题 4: 实现一个算法,将一个整数数组按照奇数在前,偶数在后的顺序重新排列。
答案:```pythondef rearrange_array(arr):odd = []even = []for num in arr:if num % 2 == 0:even.append(num)else:odd.append(num)return odd + even```试题 5: 给定一个链表,删除链表的倒数第n个节点。
答案:1. 遍历链表,找到链表的长度。
2. 再次遍历链表,找到倒数第n个节点的前一个节点。
3. 将前一个节点的next指针指向当前节点的下一个节点。
4. 如果当前节点是头节点,则更新头节点。
试题 6: 编写一个函数,实现字符串反转。
答案:```pythondef reverse_string(s):return s[::-1]```试题 7: 给定一个整数数组,找出数组中没有出现的最小正整数。
答案:1. 遍历数组,使用哈希表记录出现的数字。
2. 从1开始,检查每个数字是否在哈希表中。
3. 第一个不在哈希表中的数字即为答案。
试题 8: 实现一个算法,计算斐波那契数列的第n项。
程序员必做的100道题
程序员必做的100道题作为一名程序员,不仅需要掌握各种编程语言和技术,还需要不断提升自己的编程能力和解决问题的能力。
为了帮助程序员们更好地锻炼自己,下面列举了100道程序员必做的题目,希望能够对广大程序员朋友们有所帮助。
1. 实现一个二分查找算法。
2. 实现一个冒泡排序算法。
3. 实现一个快速排序算法。
4. 实现一个选择排序算法。
5. 实现一个插入排序算法。
6. 实现一个归并排序算法。
7. 实现一个堆排序算法。
8. 实现一个希尔排序算法。
9. 实现一个计数排序算法。
10. 实现一个桶排序算法。
11. 实现一个基数排序算法。
12. 实现一个斐波那契数列的递归算法。
13. 实现一个斐波那契数列的非递归算法。
14. 实现一个求解最大公约数的算法。
15. 实现一个求解最小公倍数的算法。
16. 实现一个判断一个数是否为素数的算法。
17. 实现一个判断一个数是否为回文数的算法。
18. 实现一个判断一个字符串是否为回文字符串的算法。
19. 实现一个判断一个字符串是否为有效括号的算法。
20. 实现一个判断一个字符串是否为有效IP地址的算法。
21. 实现一个判断一个字符串是否为有效URL的算法。
22. 实现一个判断一个字符串是否为有效邮箱的算法。
23. 实现一个判断一个字符串是否为有效手机号的算法。
24. 实现一个判断一个字符串是否为有效身份证号的算法。
25. 实现一个判断一个字符串是否为有效银行卡号的算法。
26. 实现一个判断一个字符串是否为有效密码的算法。
27. 实现一个判断一个字符串是否为有效用户名的算法。
28. 实现一个判断一个字符串是否为有效日期的算法。
29. 实现一个判断一个字符串是否为有效时间的算法。
30. 实现一个判断一个字符串是否为有效邮政编码的算法。
32. 实现一个判断一个字符串是否为有效身高的算法。
33. 实现一个判断一个字符串是否为有效体重的算法。
34. 实现一个判断一个字符串是否为有效年龄的算法。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
1 POJ 2503 Babelfish题目大意很简单,就是给你字典的对应信息,然后给你查询条件要求你输出字典查询结果,如果字符串没有在字典中则输出"eh"。
恩,学到了一个新的函数bsearch(),可以进行二分查找。
先对字典使用qsort排序然后再使用bsearch()查找字符串即可。
还学到了一个输入函数sscanf(),可以从一个字符串中读取内容,格式如下sscanf (string str, string format [, string var1...])#include <stdio.h>#include <stdlib.h>#include <string.h>typedef struct{char en[11];char fn[11];}dict;dict a[100001];/* 定义qsort比较函数*/int q_cmp(const void * a,const void *b){return strcmp(((dict*)a)->fn, ((dict*)b)->fn);}/* 定义bsearch比较函数*/int b_cmp(const void* a, const void* b){return strcmp((char*)a, ((dict*)b)->fn);}int main(){char str[30];int i, sign;dict *p;i = 0;/* 查询标记记为"未开始" */sign = 1;/* 读取字符串直到文件结束*/while(gets(str)){/* 遇到空行则开始排序字典*/if (str[0] == '\0'){/* 查询标记记为"开始" */sign = 0;qsort(a, i, sizeof(dict), q_cmp);continue;}/* 查询未开始时读取字典信息*/if (sign){/* 使用sscanf从str中读取查询要求*/sscanf(str, "%s %s", a[i].en, a[i].fn);i++;}/* 查询开始时进行查询*/else{/* 二分查找指定字符串*/p = (dict*) bsearch(str, a, i, sizeof(dict), b_cmp);/* 找到则输出结果*/if (p){puts(p->en);}/* 找不到输出"eh" */else{puts("eh");}}}//system("pause");return 0;}2 POJ 2513 Colored Sticks 欧拉通路+并查集+trie树这道题大意是:已知有n根木棒,每个木棒有两种颜色表示两端,问:能不能将所有的木棒连接成一条直线(连接处颜色相同)。
可以考虑无向图的欧拉通路问题:将每种颜色看成图中的一个节点,木棒看作连接节点的边,于是判断两点:1,每种颜色(节点)的度2,是否为连通图首先,每种颜色的度可以通过每条木棒的两端颜色的累积得到,问题是,每种颜色都是字符串,怎么关联每种颜色和度呢?最容易想到的是Hash,这肯定是可行的。
例如degree [ hash(red) ]=5。
表示颜色为红色的度为5。
但是,既然提示用trie树来做,那么trie树的节点的数据域就可以保存每种颜色的id(相当于分配的hash值,可以通过一个全局变量自增产生),这样经过将每种颜色字符串插入到tree 中以后,通过trie树的search操作就能高效的获取每种颜色对应的id,没插入一种颜色,为其产生一个id,只需要注意相同颜色插入时的处理即可。
其次,判断无向图是否连通可以使用并查集来判定:经过n-1各union操作后,所有节点都在一个集合(树形结构表示集合的话,即所有节点的父节点(集合代表)都一样)。
由于每种颜色是由字符串来标示的,每个集合保存颜色对应的唯一id。
通过上面两个步骤的判定,就可以得出结果。
#include <iostream>#include <cstring>using namespace std;const int max_size=500001;char s1[11],s2[11];int p[max_size];int r[max_size];int degree[max_size];int num=1;struct TreeNode{int id;//the id of the stringTreeNode * next[27];TreeNode (){id=0;for(int i=0;i<27;i++)next[i]=NULL;}};TreeNode * root;void insert(char *s ,TreeNode * root){TreeNode *p = root;int i = 0;int l = strlen(s);for(i=0;i<l;i++){if(p->next[s[i]-'a']==NULL)p->next[s[i]-'a']=new TreeNode;p=p->next[s[i]-'a'];}if(p->id==0)//first insertp->id = num++;}int search(char *s,TreeNode *root){TreeNode * p = root;if(p==NULL)return -1;int i=0;int l = strlen(s);for(i=0;i<l;i++){if(p->next[s[i]-'a']==NULL)return -1;elsep=p->next[s[i]-'a'];}return p->id;}void make_set(int x){p[x]=x;r[x]=1;}int find_set(int x){if(p[x]!=x)p[x]=find_set(p[x]);return p[x];}void union_set(int x,int y){p[y]=x;else if(r[x]<r[y])p[x]=y;else{r[y]++;p[x]=y;}}int main(){root = new TreeNode;memset(p,0,sizeof(p));memset(degree,0,sizeof(degree));while(scanf("%s %s",s1,s2)!=EOF){insert(s1,root);insert(s2,root);int id1 = search(s1,root);int id2 = search(s2,root);degree[id1]++;degree[id2]++;if(p[id1]==0)make_set(id1);if(p[id2]==0)make_set(id2);union_set(find_set(id1),find_set(id2));}int i = 0;int sum=0;//if the num of nodes whose degree is odd are more than 2.for(i=1;i<num;i++){if(degree[i]%2!=0)sum++;if(sum>2){cout<<"Impossible"<<endl;return 0;}}//if the g is joint.for(i=1;i<num;i++)if(find_set(i) != find_set(1))cout<<"Impossible"<<endl;return 0 ;}cout<<"Possible"<<endl;}3 poj 1035 Spell checker开始做字符串的题目,本人觉得最头痛噶野,好鬼唔锺意处理字符串噶野。
不过唯有硬住头皮上啦。
呢条题有个奇怪噶地方,就系用STL做的话,点都系TLE,后来改翻用C语言甘样慢慢搞先过,重要用左将近1s.注意:(1)用另一个字符数组记录字典,然后排序,用于二分查找的。
(2)先处理与被检查数组相同长度的,然后系,比距长的,最后系比距短的。
(3)数组开得足够大啦#include<iostream>#include<stdio.h>#include<cstring>using namespace std;int cmp(const void *p, const void *q) {return strcmp((char *) p, (char *) q);}struct s {char word[20];int len;} str1[10005];char str2[10005][20], bc[20], ch[20], *p;int bcl, n;void input() {int i = 0;while (strcmp(gets(str1[++i].word), "#")) {str1[i].len = strlen(str1[i].word);strcpy(str2[i], str1[i].word);}n = i;qsort(str2 + 1, n, sizeof (str2[0]), cmp);}void solve() {int i, j, k;while (strcmp(gets(bc), "#")) {bcl = strlen(bc);p = (char *) bsearch(&bc, str2 + 1, n, sizeof (str2[0]), cmp);if (p)cout << bc << " is correct" << endl;else {cout << bc << ":";for (i = 1; i <= n; i++) {if (str1[i].len == bcl) {int flag = 0;for (j = 0; j < str1[i].len; j++) {if (str1[i].word[j] != bc[j])flag++;}if (flag < 2) cout << " " << str1[i].word;} else if (bcl == str1[i].len + 1) {for (j = 0; j < bcl; j++) {strcpy(ch, bc);for (k = j; k < bcl; k++)ch[k] = ch[k + 1];//cout<<bc<<" "<<str1[i].word<<" "<<ch<<endl;if (strcmp(ch, str1[i].word) == 0) {printf(" %s", str1[i].word);break;}}} else if (bcl == str1[i].len - 1) {for (j = 0; j < str1[i].len; j++) {strcpy(ch, str1[i].word);for (k = j; k < str1[i].len; k++)ch[k] = ch[k + 1];//cout<<bc<<" "<<str1[i].word<<" "<<ch<<endl;if (strcmp(ch, bc) == 0) {printf(" %s", str1[i].word);break;}}}}cout << endl;}}}int main() {input();solve();return 0;}4 POJ 1200 Crazy Search这个是说一段字符串有nc种字符组成问长度为n的不同的字符串有多少个非常关键的一条信息是nc^n最多只有16 000 000so 我们用nc进制的HASH来做#include <stdio.h>#include <string.h>int n,nc;char str[20000000];char asca[128];int hash[16000005];int main(){while(scanf("%d%d\n",&n,&nc)!=EOF){scanf("%s",str);int i=0;int j;int key=0;while(str[i]){if(asca[str[i]]==0) asca[str[i]]=++key;i++;if(key==nc) break;}int len=strlen(str);int sum;int cnt=0;for(i=0;i+n-1<len;i++){sum=0;for(j=i;j<=i+n-1;j++){sum=sum*nc+asca[str[j]]-1;}if(hash[sum]==0){hash[sum]=1;cnt++;}}printf("%d\n",cnt);}}5 POJ 2002 hash(枚举+哈希)简单hash,具体做法是枚举任意两个点,因为有这由两个点所构成的边属于某个正方形那么可以计算出属于该正方形的另外两个点。