c++编程入门第一次课_第1页
c++编程入门第一次课_第2页
c++编程入门第一次课_第3页
c++编程入门第一次课_第4页
c++编程入门第一次课_第5页
已阅读5页,还剩47页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

一、编程思想和语言基础王振昊绪论为什么要学习编程Oier的尴尬地位怎样学好编程课表时间段安排2月1号2月2号2月3号2月4号2月5号上午讲解(8:30-10:30)了解学生需求

语言:(含结构体与

基本语言技巧)暴力(含BFS、DFS)动态规划及相关应用语言贪心二分(以例题和较深的讲解为主)Dp的讲解

数学(扩欧、唯一分解,二项式定理、快速幂)练习(10:30-11:30)语言题、答疑暴力题目、答疑动态规划习题、答疑语言题+贪心+二分数学+Dp习题下午讲解(14:30-17:00)递归二分贪心图论(并查集、生成树、最短路)递归与递推

Dp的一些讲解图论的理解练习(6:00-8:00)语言题、递归习题、答疑二分、贪心简单习题图论习题、答疑语言题+贪心+二分Dp的简单习题图论习题(较基础)王振昊薛鑫磊一、编程思想和语言基础1.1编程思想1.2C/C++语言初步1.3结构体(记录类型)1.4高精度计算1.1编程思想

程序(program)是为实现特定目标或解决特定问题而用计算机语言编写的命令序列的集合。为进行某活动或过程所规定的途径。编程就是让计算机为解决某个问题而使用某种程序设计语言编写程序代码,并最终得到结果的过程。为了使计算机能够理解人的意图,人类就必须要将需解决的问题的思路、方法、和手段通过计算机能够理解的形式告诉计算机,使得计算机能够根据人的指令一步一步去工作,完成某种特定的任务。这种人和计算机之间交流的过程就是编程。因此,一个好的程序员必须学会从计算机的角度去思考问题1.1编程思想举几个例子:Swap冒泡排序和插入排序辗转相除法计算几何1.1编程思想著名计算机科学家沃思提出一个公式:数据结构+算法=程序。实际上,一个程序除了以上两个主要的要素外,还应当采用程序设计方法进行设计,并且用一种计算机语言来表示。因此,算法、数据结构、程序设计方法和语言工具4个方面是一个程序员所应具备的知识。1.1编程思想推荐几本经典的书1.2C/C++语言初步C语言是一种计算机程序设计语言,它既具有高级语言的特点,又具有汇编语言的特点。随着微型计算机的日益普及,出现了许多C语言版本。由于没有统一的标准,使得这些C语言之间出现了一些不一致的地方。为了改变这种情况,美国国家标准研究所(ANSI)为C语言制定了一套ANSI标准,成为现行的C语言标准。C语言是世界上最流行、使用最广泛的高级程序设计语言之一。1.2C/C++语言初步先从简单的入手: A+BProblem:

输入格式:

两个自然数a和b(0<=a,b<=32767)

输出格式:

一个数,即a和b的和1.2C/C++语言初步程序:#include<stdio.h>;intmain(){inta,b;scanf("%d%d",&a,&b);printf("%d",a+b);}1.2C/C++语言初步用程序使计算机按照题目描述过程得出结果称为模拟NOIP中第一道题往往是模拟题,也是常说的送分题,要做对这样的题,要求熟练掌握编程语言和简单基本的算法简单基本算法主要指:排序、求最大(最小)值等下面看道简单的模拟题明明的随机数题目描述:明明想在学校中请一些同学一起做一项问卷调查,为了实验的客观性,他先用计算机生成了N个1到1000之间的随机整数(N≤100),对于其中重复的数字,只保留一个,把其余相同的数去掉,不同的数对应着不同的学生的学号。然后再把这些数从小到大排序,按照排好的顺序去找同学做调查。请你协助明明完成“去重”与“排序”的工作。输入格式:输入有2行,第1行为1个正整数,表示所生成的随机数的个数:N第2行有N个用空格隔开的正整数,为所产生的随机数。输出格式:输出也是2行,第1行为1个正整数M,表示不相同的随机数的个数。第2行为M个用空格隔开的正整数,为从小到大排好序的不相同的随机数。明明的随机数本题的几种思路快速排序?冒泡排序?注意题目数据大小桶排序明明的随机数#include<stdio.h>intmain(){intser_num[1001]={0};intn,m=0,t,i,j;scanf("%d",&n);for(i=0;i<n;i++){scanf("%d",&t);ser_num[t]++;//计一个数出现的次数}明明的随机数 for(i=0;i<=1000;i++) for(j=1;j<=ser_num[i];j++) if(ser_num[i]>1) m++; printf("%d\n",n); for(i=0;i<=1000;i++) for(j=1;j<=ser_num[i];j++) if(ser_num[i]>1) printf("%d",i); printf(“\n”); return0;}1.2C/C++语言初步C++是一种面向对象的计算机程序设计语言。它是一种使用非常广泛的计算机编程语言。C++是一种静态数据类型检查的、支持多重编程范式的通用程序设计语言。它支持过程化程序设计、数据抽象、面向对象程序设计、泛型程序设计等多种程序设计风格。参考书籍:C++Primer1.3结构体(记录类型)结构体(struct),也叫结构,是由一系列具有相同类型或不同类型的数据构成的数据集合。

1.结构说明和结构变量定义

在TurboC中,结构也是一种数据类型,可以使用结构变量,因此,

象其它

类型的变量一样,在使用结构变量时要先对其定义。

定义结构变量的一般格式为:

struct结构名

{

类型

变量名;

类型

变量名;

...

}结构变量;

结构名是结构的标识符不是变量名。

1.3结构体(记录类型)

下面举一个例子来说明怎样定义结构变量。

structstring

{

charname[8];

intage;

charsex[2];

chardepart[20];

floatwage1,wage2,wage3,wage4,wage5;

}person;

1.3结构体(记录类型)其实没有什么题是必须用结构体来做的(除了用指针构建链表时),多用几个变量可以达到同样的效果。但用结构体可以增强代码的完整性和可懂性。下面看道例题:

谁拿了最多奖学金

题目描述某校的惯例是在每学期的期末考试之后发放奖学金。发放的奖学金共有五种,获取的条件各自不同:

1)院士奖学金,每人8000元,期末平均成绩高于80分(>80),并且在本学期内发表1篇或1篇以上论文的学生均可获得;

2)五四奖学金,每人4000元,期末平均成绩高于85分(>85),并且班级评议成绩高于80分(>80)的学生均可获得;

3)成绩优秀奖,每人2000元,期末平均成绩高于90分(>90)的学生均可获得;

4)西部奖学金,每人1000元,期末平均成绩高于85分(>85)的西部省份学生均可获得;

5)班级贡献奖,每人850元,班级评议成绩高于80分(>80)的学生干部均可获得;只要符合条件就可以得奖,每项奖学金的获奖人数没有限制,每名学生也可以同时获得多项奖学金。例如姚林的期末平均成绩是87分,班级评议成绩82分,同时他还是一位学生干部,那么他可以同时获得五四奖学金和班级贡献奖,奖金总数是4850元。现在给出若干学生的相关数据,请计算哪些同学获得的奖金总数最高(假设总有同学能满足获得奖学金的条件)。

谁拿了最多奖学金输入格式输入的第一行是一个整数N(1<=N<=100),表示学生的总数。接下来的N行每行是一位学生的数据,从左向右依次是姓名,期末平均成绩,班级评议成绩,是否是学生干部,是否是西部省份学生,以及发表的论文数。姓名是由大小写英文字母组成的长度不超过20的字符串(不含空格);期末平均成绩和班级评议成绩都是0到100之间的整数(包括0和100);是否是学生干部和是否是西部省份学生分别用一个字符表示,Y表示是,N表示不是;发表的论文数是0到10的整数(包括0和10)。每两个相邻数据项之间用一个空格分隔。输出格式输出包括三行,第一行是获得最多奖金的学生的姓名,第二行是这名学生获得的奖金总数。如果有两位或两位以上的学生获得的奖金最多,输出他们之中在输入文件中出现最早的学生的姓名。第三行是这N个学生获得的奖学金的总数。

谁拿了最多奖学金#include<cstdio>intmain(){charname[101][30],ganbu[101][5],xibu[101][5];intqimo[101],banji[101],wen[101],money[101]={0};intn,i,j=0,k,l=0;scanf("%d",&n);for(i=1;i<=n;i++){scanf("%s%d%d%s%s%d",&name[i],&qimo[i],&banji[i],&ganbu[i],&xibu[i],&wen[i]);if(qimo[i]>80&&wen[i]>=1)money[i]+=8000;if(qimo[i]>85&&banji[i]>80)money[i]+=4000;if(qimo[i]>90)money[i]+=2000;if(qimo[i]>85&&xibu[i][0]=='Y')money[i]+=1000;if(banji[i]>80&&ganbu[i][0]=='Y')money[i]+=850;if(money[i]>j){j=money[i];k=i;}l+=money[i];}printf("%s\n%d\n%d\n",name[k],money[k],l);return0;}1.4高精度计算利用计算机进行数值计算,有时会遇到这样的问题:有些计算要求精度高,希望计算的数的位数可达几十位甚至几百位,虽然计算机的计算精度也算较高了,但因受到硬件的限制,往往达不到实际问题所要求的精度。我们可以利用程序设计的方法去实现这样的高精度计算。介绍常用的几种高精度计算的方法。 高精度计算中需要处理好以下几个问题: (1)数据的接收方法和存贮方法 数据的接收和存贮:当输入的数很长时,可采用字符串方式输入,这样可输入数字很长的数,利用字符串函数和操作运算,将每一位数取出,存入数组中。另一种方法是直接用循环加数组方法输入数据。 voidinit(inta[])//传入一个数组 {strings; cin>>s;//读入字符串s a[0]=s.length();//用a[0]计算字符串s的位数 for(i=1;i<=a[0];i++) a[i]=s[a[0]-i]-'0';//将数串s转换为数组a,并倒序存储 }另一种方法是直接用循环加数组方法输入数据。1.4高精度计算2)高精度数位数的确定位数的确定:接收时往往是用字符串的,所以它的位数就等于字符串的长度。(3)进位,借位处理加法进位:c[i]=a[i]+b[i];if(c[i]>=10){c[i]%=10;++c[i+1];}减法借位:if(a[i]<b[i]){--a[i+1];a[i]+=10;}c[i]=a[i]-b[i];乘法进位:c[i+j-1]=a[i]*b[j]+x+c[i+j-1];x=c[i+j-1]/10;c[i+j-1]%=10;(4)商和余数的求法商和余数处理:视被除数和除数的位数情况进行处理.【例1】高精度加法。输入两个正整数,求它们的和。【分析】输入两个数到两个变量中,然后用赋值语句求它们的和,输出。但是,我们知道,在C++语言中任何数据类型都有一定的表示范围。而当两个被加数很大时,上述算法显然不能求出精确解,因此我们需要寻求另外一种方法。在读小学时,我们做加法都采用竖式方法,如图1。这样,我们方便写出两个整数相加的算法。856+2551111

图1A3A2A1+B3B2B1

C4C3C2C1

图2

如果我们用数组A、B分别存储加数和被加数,用数组C存储结果。则上例有A[1]=6,A[2]=5,A[3]=8,B[1]=5,B[2]=5,B[3]=2,C[4]=1,C[3]=1,C[2]=1,C[1]=1,两数相加如图2所示。因此,算法描述如下:intc[100];voidadd(inta[],intb[])//a,b,c都为数组,分别存储被加数、加数、结果{inti=1,x=0;//x是进位while((i<=a数组长度)||(i<=b数组的长度)){c[i]=a[i]+b[i]+x; //第i位相加并加上次的进位x=c[i]/10; //向高位进位c[i]%=10;//存储第i位的值i++;//位置下标变量}}

通常,读入的两个整数用可用字符串来存储,程序设计如下:#include<iostream>#include<cstdio>#include<cstring>usingnamespacestd;intmain(){ chara1[100],b1[100]; inta[100],b[100],c[100],lena,lenb,lenc,i,x; memset(a,0,sizeof(a)); memset(b,0,sizeof(b)); memset(c,0,sizeof(c)); gets(a1); gets(b1); //输入加数与被加数 lena=strlen(a1); lenb=strlen(b1); for(i=0;i<=lena-1;i++)a[lena-i]=a1[i]-48; //加数放入a数组 for(i=0;i<=lenb-1;i++)b[lenb-i]=b1[i]-48;//加数放入b数组 lenc=1; x=0;

while(lenc<=lena||lenc<=lenb) { c[lenc]=a[lenc]+b[lenc]+x;//两数相加 x=c[lenc]/10; c[lenc]%=10; lenc++; } c[lenc]=x; if(c[lenc]==0) lenc--;//处理最高进位 for(i=lenc;i>=1;i--) cout<<c[i];//输出结果 cout<<endl; return0;}【例2】高精度减法。输入两个正整数,求它们的差。【算法分析】类似加法,可以用竖式求减法。在做减法运算时,需要注意的是:被减数必须比减数大,同时需要处理借位。高精度减法的参考程序:#include<iostream>#include<cstdio>#include<cstring>usingnamespacestd;intmain(){ inta[256],b[256],c[256],lena,lenb,lenc,i; charn[256],n1[256],n2[256]; memset(a,0,sizeof(a)); memset(b,0,sizeof(b)); memset(c,0,sizeof(c));

printf("Inputminuend:");gets(n1);//输入被减数 printf("Inputsubtrahend:");gets(n2);//输入减数 if(strlen(n1)<strlen(n2)||(strlen(n1)==strlen(n2)&&strcmp(n1,n2)<0))//strcmp()为字符串比较函数,当n1==n2,返回0;//n1>n2时,返回正整数;n1<n2时,返回负整数 {//处理被减数和减数,交换被减数和减数 strcpy(n,n1);//将n1数组的值完全赋值给n数组 strcpy(n1,n2); strcpy(n2,n); cout<<"-";//交换了减数和被减数,结果为负数 }

lena=strlen(n1);lenb=strlen(n2); for(i=0;i<=lena-1;i++)a[lena-i]=int(n1[i]-'0');//被减数放入a数组 for(i=0;i<=lenb-1;i++)b[lenb-i]=int(n2[i]-'0');//减数放入b数组

i=1; while(i<=lena||i<=lenb) { if(a[i]<b[i]) { a[i]+=10;//不够减,那么向高位借1当10 a[i+1]--; } c[i]=a[i]-b[i];//对应位相减 i++; } lenc=i; while((c[lenc]==0)&&(lenc>1))lenc--;//最高位的0不输出 for(i=lenc;i>=1;i--)cout<<c[i];//输出结果 cout<<endl; return0;}【例3】高精度乘法。输入两个正整数,求它们的积。【算法分析】

类似加法,可以用竖式求乘法。在做乘法运算时,同样也有进位,同时对每一位进行乘法运算时,必须进行错位相加,如图3、图4。分析c数组下标的变化规律,可以写出如下关系式:ci=c’i+c”i+…由此可见,ci跟a[i]*b[j]乘积有关,跟上次的进位有关,还跟原ci的值有关,分析下标规律,有c[i+j-1]=a[i]*b[j]+x+c[i+j-1];x=c[i+j-1]/10;c[i+j-1]%=10;856×254280171221400

图3A3A2A1

×B2B1

C’4C’3C’2C’1

C”5C”4C”3C”2

C6C5C4C3C2C1图4高精度乘法的参考程序:#include<iostream>#include<cstring>#include<cstdio>usingnamespacestd;intmain(){chara1[100],b1[100];inta[100],b[100],c[100],lena,lenb,lenc,i,j,x;memset(a,0,sizeof(a));memset(b,0,sizeof(b));memset(c,0,sizeof(c));gets(a1);gets(b1);lena=strlen(a1);lenb=strlen(b1);for(i=0;i<=lena-1;i++)a[lena-i]=a1[i]-48;for(i=0;i<=lenb-1;i++)b[lenb-i]=b1[i]-48;

for(i=1;i<=lena;i++) { x=0;//用于存放进位 for(j=1;j<=lenb;j++)//对乘数的每一位进行处理 { c[i+j-1]=a[i]*b[j]+x+c[i+j-1];//当前乘积+上次乘积进位+原数 x=c[i+j-1]/10; c[i+j-1]%=10; } c[i+lenb]=x;//进位 } lenc=lena+lenb; while(c[lenc]==0&&lenc>1)//删除前导0 lenc--; for(i=lenc;i>=1;i--) cout<<c[i]; cout<<endl; return0;}【例4】高精度除法。输入两个正整数,求它们的商(做整除)。【算法分析】

做除法时,每一次上商的值都在0~9,每次求得的余数连接以后的若干位得到新的被除数,继续做除法。因此,在做高精度除法时,要涉及到乘法运算和减法运算,还有移位处理。当然,为了程序简洁,可以避免高精度除法,用0~9次循环减法取代得到商的值。这里,我们讨论一下高精度数除以单精度数的结果,采取的方法是按位相除法。#include<iostream>#include<cstring>#include<cstdio>usingnamespacestd;intmain(){ chara1[100],c1[100]; inta[100],c[100],lena,i,x=0,lenc,b; memset(a,0,sizeof(a)); memset(c,0,sizeof(c)); gets(a1); cin>>b; lena=strlen(a1); for(i=0;i<=lena-1;i++) a[i+1]=a1[i]-48;

for(i=1;i<=lena;i++)//按位相除 { c[i]=(x*10+a[i])/b; x=(x*10+a[i])%b; } lenc=1; while(c[lenc]==0&&lenc<lena) lenc++;//删除前导0 for(i=lenc;i<=lena;i++) cout<<c[i]; cout<<endl; return0;}

实质上,在做两个高精度数运算时候,存储高精度数的数组元素可以不仅仅只保留一个数字,而采取保留多位数(例如一个整型或长整型数据等),这样,在做运算(特别是乘法运算)时,可以减少很多操作次数。例如图5就是采用4位保存的除法运算,其他运算也类似。具体程序可以修改上述例题予以解决,程序请读者完成。示例:123456789÷45=1’2345’6789÷45=274’3484∵1/45=0,1%45=1∴取12345/45=274∵12345%45=15∴取156789/45=3484∴答案为2743484,余数为156789%45=9图5

【例5】高精除以高精,求它们的商和余数。 【算法分析】 高精除以低精是对被除数的每一位(这里的“一位”包含前面的余数,以下都是如此)都除以除数,而高精除以高精则是用减法模拟除法,对被除数的每一位都减去除数,一直减到当前位置的数字(包含前面的余数)小于除数(由于每一位的数字小于10,所以对于每一位最多进行10次计算)具体实现程序如下:

#include<iostream>#include<cstring>usingnamespacestd;inta[101],b[101],c[101],d,i;voidinit(inta[]){strings; cin>>s;//读入字符串s a[0]=s.length();//用a[0]计算字符串s的位数 for(i=1;i<=a[0];i++) a[i]=s[a[0]-i]-'0';//将数串s转换为数组a,并倒序存储.}voidprint(inta[])//打印输出{ if(a[0]==0){cout<<0<<endl;return;} for(inti=a[0];i>0;i--)cout<<a[i]; cout<<endl; return;}

intcompare(inta[],intb[]) //比较a和b的大小关系,若a>b则为1,a<b则为-1,a=b则为0{ if(a[0]>b[0])return1;//a的位数大于b则a比b大 if(a[0]<b[0])return-1;//a的位数小于b则a比b小 for(i=a[0];i>0;i--)//从高位到低位比较 { if(a[i]>b[i])return1; if(a[i]<b[i])return-1; } return0;//各位都相等则两数相等。}voidnumcpy(intp[],intq[],intdet)//复制p数组到q数组从det开始的地方{ for(inti=1;i<=p[0];i++)q[i+det-1]=p[i]; q[0]=p[0]+det-1;}

voidjian(inta[],intb[])//计算a=a-b{ intflag,i; flag=compare(a,b);//调用比较函数判断大小 if(flag==0){a[0]=0;return;}//相等 if(flag==1)//大于 { for(i=1;i<=a[0];i++) { if(a[i]<b[i]){a[i+1]--;a[i]+=10;}//若不够减则向上借一位 a[i]-=b[i]; } while(a[0]>0&&a[a[0]]==0)a[0]--;//修正a的位数 return; }}

voidchugao(inta[],intb[],intc[]){ inttmp[101]; c[0]=a[0]-b[0]+1; for(inti=c[0];i>0;i--) { memset(tmp,0,sizeof(tmp));//数组清零 numcpy(b,tmp,i); while(compare(a,tmp)>=0){c[i]++;jian(a,tmp);}//用减法来模拟 } while(c[0]>0&&c[c[0]]==0)c[0]--; return;}

intmain(){ memset(a,0,sizeof(a)); memset(b,0,sizeof(b)); memset(c,0,sizeof(c)); init(a);init(b); chugao(a,b,c); print(c); print(a); return0;}

【例6】回文数【问题描述】 若一个数(首位不为零)从左向右读与从右向左读都是一样,我们就将其称之为回文数。例如:给定一个10进制数56,将56加65(即把56从右向左读),得到121是一个回文数。又如,对于10进制数87,STEPl:87+78=165STEP2:165+561=726STEP3:726+627=1353STEP4:1353+3531=4884在这里的一步是指进行了一次N进制的加法,上例最少用了4步得到回文数4884。写一个程序,给定一个N(2<N<=10或N=16)进制数M.求最少经过几步可以得到回文数。如果在30步以内(包含30步)不可能得到回文数,则输出“Impossible”【输入样例】:987【输出样例】:6【算法分析】N进制运算1、当前位规范由%10改为%n2、进位处理由/10改为/n3、其他运算规则不变

【参考程序】#include<iostream>#include<cstring>usingnamespacestd;intn,a[101],b[101],ans,i;voidinit(inta[])//将数串s转化为整数数组a{ strings; cin>>n>>s;//读入字符串s memset(a,0,sizeof(a));//数组a清0 a[0]=s.length();//用a[0]计算字符串s的位数 for(i=1;i<=a[0];i++) if(s[a[0]-i]>='0'&&s[a[0]-i]<='9')a[i]=s[a[0]-i]-'0'; elsea[i]=s[a[0]-i]-'A'+10;}boolcheck(inta[])//判别整数数组a是否为回文数{ for(i=1;i<=a[0];i++) if(a[i]!=a[a[0]-i+1])returnfalse; returntrue;}

voidjia(inta[])//整数数组a与其反序数b进行n进制加法运算{ for(inti=1;i<=a[0];i++)b[i]=a[a[0]-i+1];//反序数b for(inti=1;i<=a[0];i++)a[i]+=b[i];//逐位相加 for(inti=1;i<=a[0];i++)//处理进位 {a[i+1]+=a[i]/n; a[i]%=n; } if(a[a[0]+1]>0)a[0]++;//修正新的a的位数(a+b最多只能的一个进位)}intmain(){ init(a); if(check(a)){cout<<0<<endl;return0;} ans=0;//步数初始化为0 while(ans++<=30) {jia(a); if(check(a)){cout<<ans<<endl;return0;} } cout<<"Impossible";//输出无解信息 return0;}【上机练习】1、求N!的值【问题描述】

用高精度方法,求N!的精确值(N以一般整数输入)。【输入样例】ni.in10【输出样例】ni.out36288002、求A/B高精度值【问题描述】

计算A/B的精确值,设A,B是以一般整数输入,计算结果精确小数后20位。【输入样例】ab.in43【输出样例】ab.out4/3=1.33333333333333333333【输入样例】ab.in65【输出样例

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论