行亦谦ACM自闭之旅第一周


本周收获的基础知识(2022.7.14-2022.7.17)

(1)向下取整函数:double floor(double x);

 使用floor函数。floor(x)返回的是小于或等于x的最大整数。
 提示:函数floor(x)返回x的整数部分,使用floor(m+0.5)==m的原因是浮点数的运算
 (和函数)有可能存在误差。

(2)向上取整函数:double ceil(double x);

 使用ceil函数。ceil(x)返回的是大于x的最小整数。

(3)while(scanf("%d", &x) == 1)

          scanf函数的返回值是成功输入的变量个数。当输入结束时,scanf无法再次读取x,将返回0。
         在Windows下,输入完毕后先按Enter键,再按Ctrl+Z键,最后再按Enter键,即可结束键入
         。 在Linux下,输入完毕后按Ctrl+D键即可结束输入。

(4)变量在未赋值之前的值是不确定的。特别地,它不一定等于0。

      方法1.INF=1000000000, max=INF,min=-INF
      方法2. 先读取第一个整数x,然后令max=min=x。
      由于min保存的是最小值,它的初值应该是一个很大的数; 

基本输入(重点)

第一类输入

输入不说明有多少个Input Block,以EOF为结束标志。

源代码如下:
#include <stdio.h>
int main()
{ 
      int a,b;
 	  while(~scanf("%d %d",&a, &b))  	printf("%d\n",a+b);
} 
本类问题的输入方案为:
①	C语法
while(~scanf("%d %d",&a, &b)) //返输入
{
  ....
} 
②C++语法
while( cin >> a >> b ) 
{ 
   .... 
} 
说明:①scanf函数返回值就是读出的变量个数,如:scanf("%d  %d", &a, &b ); ,
如果只有一个整数输入,返回值是1;如果有两个整数输入,返回值是2;如果一个都没有,
则返回值是-1。
②EOF是一个预定义的常量,等于-1。

第二类输入
输入一开始就会说有n个Input Block,下面接着是输入n个Input Block。
参见:HDOJ_1090(http://acm.hdu.edu.cn/showproblem.php?pid=1090)。

源代码如下:
#include <stdio.h>
int main()
{ 
   int n;
scanf("%d",&n); 
while(n--){
	int a,b;
 	    scanf("%d %d",&a, &b);
   	printf("%d\n",a+b);
   }
 } 
本类问题的输入方案为:
①C语法
scanf("%d",&n); 
while(n--){ 
    .... 
} 
②C++语法
cin >> n; 
while(n--){ 
    .... 
} 

第三类输入
输入不说明有多少个Input Block,但以某个特殊输入为结束标志。
参见:HDOJ_1091(http://acm.hdu.edu.cn/showproblem.php?pid=1091)。

源代码如下:
#include <stdio.h>
 int main()
 { 
	int a,b;
	while(~scanf("%d %d",&a, &b) &&(a!=0 && b!=0))
   	 printf("%d\n",a+b);
 } 
上面程序有什么问题?
本类问题的输入方案为:
①	C语法
while(~scanf(“%d”,&n) && n!=0 ) 
{
  .... 
} 

②C++语法
while( cin >> n && n != 0 ) 
{ 
   .... 
} 

第四类输入
输入一整行的字符串。
参见:HDOJ_1048(http://acm.hdu.edu.cn/showproblem.php?pid=1048)。

本类问题的输入方案为:
①C语法
char buf[20]; 
gets(buf); 
②C++语法
如果用string buf;来保存,则用语句getline( cin , buf ); 。
如果用char buf[ 255 ]; 来保存,则用语句	cin.getline( buf, 255 );。
说明:①scanf("%s%s",str1,str2),在多个字符串之间用一个或多个空格分隔;
②若使用gets函数,应为gets(str1); gets(str2); 字符串之间用回车符作分隔。
③通常情况下,接受短字符用scanf函数,接受长字符用gets函数。
④getchar函数每次只接受一个字符,经常c=getchar()这样来使用。
⑤cin.getline的用法
getline 是一个函数,它可以接受用户的输入的字符,直到已达指定个数,或者用户输入了特定的字符。它的函数声明形式(函数原型)如下:
istream& getline(char line[], int size, char endchar='\n');
不用管它的返回类型,来关心它的三个参数:
char line[]就是一个字符数组,用户输入的内容将存入在该数组内。
int size表示最多接受几个字符?用户超过size的输入都将不被接受。
char endchar表示当用户输入endchar指定的字符时,自动结束。默认是回车符。
结合后两个参数,getline可以方便地实现:用户最多输入指定个数的字符,如果超过,则仅指定个数的前面字符有效,如果没有超过,则用户可以通过回车来结束输入。
char name[4];
cin.getline(name,4,'\n');
由于endchar 默认已经是 '\n',所以后面那行也可以写成:cin.getline(name,4);。

基本输出

第一类输出
一个Input Block对应一个Output Block,Output Block之间没有空行。
参见:HDOJ_1089(http://acm.hziee.edu.cn/showproblem.php?pid=1089)。

本类问题的输出方案为:
①C语法
{
   ....
   printf("%d\n",ans); 
} 
②C++语法
{ 
    ...
cout << ans << endl; 
} 

第二类输出
一个Input Block对应一个Output Block,每个Output Block之后都有空行。
参见:HDOJ_1095(http://acm.hdu.edu.cn/showproblem.php?pid=1095)。

源代码如下:
#include <stdio.h>
int main()
{ 
    int a,b;
 	while(scanf("%d %d",&a, &b) != EOF)   printf("%d\n\n",a+b);
} 
解决办法如下:
①C语法
{
   ....
   printf("%d\n\n",ans); 
} 
②C++语法
{
    ... 
    cout << ans << endl << endl; 
} 

第三类输出
一个Input Block对应一个Output Block,Output Block之间有空行。
参见:HDOJ_1096(http://acm.hdu.edu.cn/showproblem.php?pid=1096)。

源代码如下:
#include <stdio.h>
int main()
{ 
    int icase,n,i,j,a,sum;
    scanf("%d",&icase);
    for(i=0;i<icase;i++)
  {
	     sum=0;
         scanf("%d",&n);
	     for(j=0;j<n;j++)
	     {
	         scanf("%d",&a);
             sum+=a;
	     }
	     if(i<icase-1)
   	        printf("%d\n\n",sum);
         else
 	        printf("%d\n",sum);
     }
} 
解决办法如下:
①C语法
for (k=0;k<count;k++) 
{ 
    while (…) 
    { 
         printf("%d\n",result);
    } 
    if(k!=count-1)  printf("\n"); 
} 
②C++语法
类似,输出语句换一下即可。

补充:OJ上提交代码后出现的提示

在OJ上提交代码后,会弹出处理页面,然后单击处理页面上的Status(状态)链接,会弹出状态页。
状态页面显示了Run ID、Submit time、Judge Status(评测状态)、Problem ID、Language、Run time(时间开销)、Run memory(内存开销)、User Name等几个信息。Judge Status(评测状态)一般有以下情况。
Accepted:恭喜,通过。
Presentation Error:输出格式错误。
Wrong Answer:答案错误。
Runtime Error:程序运行时发生错误,多为数组访问越界。
Time Limit Exceeded:超内存错误,程序运行使用的内存超过限制的内存用量。
Compile Error:编译错误,源代码中有语法错误。

提示:以下是本篇文章正文内容,下面案例可供参考

一、C++入门

(1)常用头文件(标准库)

(在C++程序中使用C语言头文件,将末尾的".h"去除,并在开头加上"c")

#include <cstdio>  //功能和C中的stdio.h很接近,但有些许不同
#include <cmath>//<math.h>
#include <cstring>//<string.h>
#include <bits/stdc++.h>//万能头文件
#include <cstdlib>//<stdlib.h>

(2)C++的流输入输出

cin >> //输入流中提取数据
cout << //控制台输出
endl  || "\n" //换行
#include <iostream>  //头文件iostream包含了对输入输出流的定义
using namespace std;//为了避免添加该限定符(std)
int main(){
    int a,b;
    while(cin>>a>>b)  
    cout<<a+b<<"\n";
    return 0;
}

(3)C++的库函数

#include <algorithm>     // 引用算法库
sort(a,a+10,cmp);        // 排序函数,时间复杂度是nlogn
swap(a,b);               // 交换函数
memset(a,0,sizeof(a));   //作用是把数组a清零

二.字符串

memcpy函数

原型:void *memcpy(void *dest, void *src, unsigned int count);
memcpy(b,a,sizeof(int)*k);   //从数组a复制到k个元素到数组b
memcpy(b,a,sizeof(double)*k);//数组a和b都是浮点型的
memcpy(b,a,sizeof(a));       //数组a全部复制到数组b

memset函数

原型:void *memset(void *buffer, char c, int count);

atoi函数

int atoi(char *s)//字符串返回整型数//<stdlib.h>

itoa函数

char *itoa(int value,char *string,int radix)//整型数返回字符串//<stdlib.h>

strchr函数

char *strchr(const char *s,char c);//找字符串s中首次出现字符c的位置。
//它的返回值是返回首次出现c的位置的指针,如果s中不存在c则返回NULL。
//包含此函数的头文件是string.h。

strlen(s)函数

 int len = strlen(str)//作用是获取字符串s的实际长度,
 //即函数strlen(s)返回的是结束标记之前的字符个数<string.h>
 //注:C语言的字符串是以空字符'\0'结尾,所以字符串的空间应为字符个数加1,s[strlen(s)]正是结束标记'\0'。

提示:由于字符串的本质是数组,它也不是“一等公民”,只能用strcpy(a,b)、strcmp(a,b)、strcat(a,b)来执行“赋值”、“比较”和“连接”操作(仅限一维数组)。而不能用=、==、<=、+等运算符。上述函数都在string.h中声明。

getchar()函数

功 能: 从stdio流中读字符
用 法: int getchar(void);
getchar函数的返回值是用户输入的第一个字符的ASCII码,如出错返回-1。
用法:在主函数结尾,return 0;之前加上getchar();
include <stdio.h>
int main(void)
{
	int c;
	while ((c = getchar()) != -1)
//while ((c = getchar()) != EOF)
		printf("%c", c);
	return 0;

fgets()函数

函数原型:char *fgets(char *buf, int bufsize, FILE *stream); 
参数: *buf: 字符型指针,指向将存储到的数据地址。
bufsize: 整型数据,指明buf指向的字符数组的大小。
*stream: 文件结构体指针,将要读取的文件流。
功能:从文件结构体指针stream中读取数据,每次读取一行。读取的数据保存在buf指向的字符数组中,每次最多读取bufsize-1个字符(第bufsize个字符赋'\0'),如果文件中的该行,不足bufsize个字符,则读完该行就结束。如果函数读取成功,则返回指针buf,失败则返回NULL

gets()函数

头文件:stdio.h(c中),c++不需包含此头文件
原  型:char *gets(char *buffer);
功  能:从stdio流中读取字符串,直至接受到换行符或EOF时停止,并将读取的结果存放在buffer指针所指向的字符数组中。换行符不作为读取串的内容,读取的换行符被转换为null值,并由此来结束字符串。
返回值:读入成功,返回与参数buffer相同的指针;读入过程中遇到EOF(End-of-File)或发生错误,返回NULL指针。所以在遇到返回值为NULL的情况,要用ferror或feof函数检查是发生错误还是遇到EOF

注意:本函数可以无限读取,不会判断上限,所以程序员应该确保buffer的空间足够大,以便在执行读操作时不发生溢出。如果溢出,多出来的字符将被写入到堆栈中,这就覆盖了堆栈原先的内容,破坏一个或多个不相关变量的值,为了避免这种情况,我们可以用fgets()来替换gets()。
提示:C语言中的gets(s)存在缓冲区溢出漏洞,不推荐使用。

clock函数

clock_t  clock(void);
clock函数是C/C++中的计时函数,而与其相关的数据类型是clock_t。

时间复杂度
用O(n)表示,表示算法的时间复杂度。
多项式的时间复杂度是可优化的,要避免指数型的时间复杂度。

三、题目小结

实践收获

(1)不同编译器的功能不同,AC的代码在一些编译器上无法运行,遇到这种情况换几个编译器试试
(2)运行超时解决方法

1.减少不必要的循环
2.打表(减少工作)
3.时间复杂度
递归:最慢的方法,查找重复极多。
记忆化搜索:在递归基础上进行优化,去重,效率提升。
递推:最快的,代码短,关系式不太容易弄懂。

例一、F - The 3n + 1 problem

Problems in Computer Science are often classified as belonging to a certain class of problems (e.g., NP, Unsolvable, Recursive). In this problem you will be analyzing a property of an algorithm whose classification is not known for all possible inputs.

Consider the following algorithm:


    1.      input n

    2.      print n

    3.      if n = 1 then STOP

    4.           if n is odd then n <- 3n + 1

    5.           else n <- n / 2

    6.      GOTO 2


Given the input 22, the following sequence of numbers will be printed 22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1

It is conjectured that the algorithm above will terminate (when a 1 is printed) for any integral input value. Despite the simplicity of the algorithm, it is unknown whether this conjecture is true. It has been verified, however, for all integers n such that 0 < n < 1,000,000 (and, in fact, for many more numbers than this.)

Given an input n, it is possible to determine the number of numbers printed (including the 1). For a given n this is called the cycle-length of n. In the example above, the cycle length of 22 is 16.

For any two numbers i and j you are to determine the maximum cycle length over all numbers between i and j.
Input
The input will consist of a series of pairs of integers i and j, one pair of integers per line. All integers will be less than 1,000,000 and greater than 0.

You should process all pairs of integers and for each pair determine the maximum cycle length over all integers between and including i and j.

You can assume that no opperation overflows a 32-bit integer.
Output
For each pair of input integers i and j you should output i, j, and the maximum cycle length for integers between and including i and j. These three numbers should be separated by at least one space with all three numbers on one line and with one line of output for each line of input. The integers i and j must appear in the output in the same order in which they appeared in the input and should be followed by the maximum cycle length (on the same line).
Sample
Inputcopy	Outputcopy
1 10
100 200
201 210
900 1000
1 10 20
100 200 125
201 210 89
900 1000 174

AC answer(打表法)

#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const int M = 1e6; 
int c[M + 5];//c数组储存每个数字所跑的长度

int main( )
{
	int a, b, j;
	while (cin >> a >> b) {
		cout << a << " " << b << " ";
		if (a > b) {
			j = a; a = b; b = j;
		}
		int s = 0;
		for (int i = a; i <= b; i++) {
			if (c[i] == 0) {//若为0,则表示该数字还未通过代码实现
			                //本地打表
			                //若不为0,则该数字已实现,可以直接调用该结果,
			                //无需再重复计算
				for (j = a; j <= b; j++) {
					int sum = 1, t = j;
					while (t != 1) {
						if ( t % 2 == 1) {
							t = 3 * t + 1;
						}
						else {
							t /= 2;
						}
						sum++;
				     }
					c[j] = sum;
				}	
			}
			 s = max(s, c[i]);	
		}
		cout << s << "\n";
	}
	return 0;
}

例二.蛇形矩阵

#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
int a[25][25];
int dr[]={1,0,-1,0};//行偏移,下左右上
int dc[]={0,-1,0,1} ;//列偏移,下左右上
int main()
{
	int n;
	cin >> n;
	int r = 1, c = n; //第1行第n列开始填数
	int x =0 ;        //先往下
	//蛇形填数,填入n*n个数
	for(int i = 1;i <= n* n;i++){
		a[r][c] = i ;
		// printf("a[%d][%d]= %d",r,c,i);
		//试探新行nr和新列nc
		int nr = r + dr[x];
		int nc = c + dc[x];
		//出界就拐弯或者填过数就拐弯
		if(nr<1 || nr> n || nc < 1 || nc > n|| a[nr][nc]>0){
			x = ( x + 1 )%4;   
		}
		r += dr[x];
        c += dc[x];
        // printf("\tr = %d,c = %d\n",r,c);
	}
	    //输出n阶方阵
	    for(int i = 1;i <= n;i++){
	    	for(int j = 1;j <= n;j++){
	    		cout << a[i][j]<<" ";
			}
			cout << endl;
		}
		return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值