机试编程总结

简介: 如果数组大小较大(大概10^6)则需要定义在main函数外,否则会使程序异常退出(因为函数内部申请的局部变量来自系统栈,即允许申请的空间较小;而函数外部申请的全局变量来自【静态存储区】,即允许申请的空间较大)

1.申请数组

如果数组大小较大(大概10^6)则需要定义在main函数外,否则会使程序异常退出(因为函数内部申请的局部变量来自系统栈,即允许申请的空间较小;而函数外部申请的全局变量来自【静态存储区】,即允许申请的空间较大)。

2.scanf的%c和%s

scanf的%c格式时可以读入空格和换行\n的;%d的输入则是以空白符(即空格、换行等)作为结束判断标志。

字符数组使用%s格式读入时的结束标志:空格、换行符。

#include <stdio.h>
int main(){
    int a;
    char c,str[10];   
    scanf("%d%c%s",&a,&c,str);
    printf("a=%d,c=%c,str=%s",a,c,str);
    system("pause");
}

输入的结果是:1 a bcd

输出的结果是:a=1,c= ,str=a

int型变量a遇到空格时停止读入(a不包含空格);而char型字符变量c(注意不是字符串变量)实际是一个空格——%c可以读入空格;str字符串变量为a(a后面即空格——结束)。

3.double

double型变量的输出格式为%d,而scanf输入的格式时%ld。

对于浮点型,不要使用float(因为精度只有6~7位),即只要是浮点型就使用double型最保险。

4.无穷大数

const int INF=(1<<30)-1;
const int INF=0x3fffffff;

上面两种写法都是可以的;注意1<<30必须加括号(因算术运算符的优先级高于位运算符)。

如果是定义long long型的最大值则是long long inf=(1 long long <<63)-1;

注意:const用来定义常量,如const double pi=3.14;

另一种定义符号常量的方式是:【宏定义】#define pi 3.14

5.memset赋值

(1)添加头文件#include <string.h>

(2)用memset给数组赋值全部为0或-1(因为memset是按字节赋值,即组成int型的4个字节都会被赋成相同值——0的二进制补码为全0,-1的二进制补码为全1)

——memset(数组名,值,sizeof(数组名))。

(3)若对数组赋值其他数字(如1)则使用fill函数。

6.字符数组2种初始化

(1)和普通数组一样逐个赋值:char str[15]={'g','m','s'};

(2)直接通过字符串初始化(只有初始化可以,其他地方不能这样直接赋值整个字符串):

char str[15]="guomiansheng"

打印则用for循环逐个;printf("%c",str[i])

7.用while接收输入

// 使⽤while接收输⼊的两种⽅式
while(scanf("%d", n) != EOF) {
}
// 等价于下⾯这种:
//因为EOF⼀般为-1,所以~按位取反-1正好是0,就可以退出循环了
//所以也写成下⾯这种情况
while(~scanf("%d", &n)) {
}

如果在自己的编译器运行后的命令行这样做会得不到输出结果(因为计算机一直在等你的输入结束,你需要在黑框中手动输入后,用<Ctrl+Z>组合键后按<Enter>键来高速系统已经到达了EOF即到达了所谓的“文件末尾”——这样系统才会结束while),但是OJ却能AC,因为OJ会自己判断输入文件有没有已经读取完。

8.说反话

实现的效果是【输入】Hello World Here I Come;【输出】Come I Here World Hello。

——相当于结合了第二条笔记和第七条笔记,用while循环接收输入,一直输入直到文件末尾:

#include<cstdio>
int main(){
    int num=0;//单词的个数
    char ans[90][90];
    while(scanf("%s",ans[num]!=EOF)){//一直输入直到文件末尾
        num++;//单词个数加1
    }
    for(int i=num-1;i>=0;i==){//倒着输出单词
        printf("%s",ans[i]);
        if(i>0) printf(" ");
    }
    system("pause");
}

9.sort排序

(1)sort默认是从小到大排序,可以使用cmp改变排序规则;

(2)注意排序cmp写法,如下面栗子:如果a和b身高不同则按从大到小的身高排序,如果a和b的身高相同则按名字降序排序。

(3)记忆方法:return的“大于”就是按从大到小排列。

struct node{
  string name;
  int height;
};
int cmp(struct node a,struct node b){
  return a.height != b.height ?a.height>b.height:a.name<b.name;
}
sort(v.begin(),v,end(),cmp);

10.字符串hash(进制转换)

若要一个字符串S哈希映射为一个整数(唯一),26个大写字母对应到二十六进制中,即将二十六进制转为十进制,但若字符串包含小写字母则是将五十二进制转换为十进制(若字符串包含数字,就将进制数增大为62):

int hashFunc(char S[],int len){//hash函数,将字符串S转为整数
    int id=0;
    for(int i=0;i<len;i++){//如果len未知,可以用strlen(S)
        if(S[i]>='A'&&S[i]<='Z'){
            id=id*52+(S[i]-'A');
        }else if(S[i]>='a'&&S[i]<='z'){
            id=id*52+(S[i]-'a')+26;
        }
    }
    return id;
}

11.判断素数

1. bool isprime(int n){
2. for(int i=2;i*i<=n;i++)
3. if(n%i==0) return false;
4. return true;
5. }

12.sort进阶

sort排序默认是从小到大,如果要从大到小排序:(注意functional的头文件):

#include<algorithm>
#include<functional>
int a[100000];
sort(a,a+n,greater<int>());
//或者
int cmp(int a,int b){return a>b;}
sort(a,a+n,cmp);

符号重载的node结构体作为set的元素自动排序(按频率cnt降序,如cnt同则编号升序)

注意运算符重载在结构体中的写法:

struct node{
  int value,cnt;
  bool operator<(const node &a)const{
    return (cnt!=a.cnt)?cnt>a.cnt:value<a.value;
    //第一优先级:频率降次  第二优先级:编号
  }
};

13.

PAT刷题tips

3.倒置输出vector内容

#include <iostream>
#include <vector>
using namespace std;
int main(){
    vector<int> vec;
    for (int i = 0; i < 5; ++i) vec.push_back(i);
    vector<int>::reverse_iterator it;
    for (it = vec.begin(); it != vec.end(); it++)
        cout<<*it<<" ";
    cout<<endl;
}

5.优先级(简):!> 算术运算符 > 关系运算符 > && > || > 赋值运算符

【口诀】:算关与或赋值(盘算关羽或者这对父子)

7.cin读入字符串是以空格为分隔符,要读入以一整行(包括空格)用getline

#include<string>
string s;
getline(cin,s);
cout<<s.length();//输出字符串长度

8.段错误~访存越界等

解决方法(在pat系统上)

while(1)大法   【原理】pat在段错误及时跳出错误,若到了while(1)则显示超时错误

9.二级指针

struct node{
    int data;//数据域
    node *left,*right;//指针域
};
void insert(node* &root,int data){
....}

main函数内调用

int main(){
...
    node* root=NULL;
    insert(root,data);
...
    return 0;
}

10.递归~return~【A1135】

12.map<string,int>的int初始值为0

13.vector< int > ivec( ia, ia+6 ) //指将ia数组的6个元素复制到vector中

14.参考“日沉浮起”dalao的github的代码模板

https://github.com/richenyunqi/Common-code-templates-for-ACM-PAT-CSP-OJ-topics

15.一定要注意多个for循环的循环变量i不能写混乱,可以为i、ii、iii

16.printf("%04d",a);//注意默认是左对齐,如:-1占4格的最左边

17.有重复功能模块的地方不能单纯复制,一定要看清楚哪些需要改动!!如i和j

18.万能头文件 #include<bits/stdc++.h>

20.a&=b等价于a=a&b

21.已知先序&后序构造二叉树:

1.前序的首结点=后序的末结点=根结点,用一刀砍成左&右子树

2.前序的第二个结点即左子树的根结点,同时要找到这个结点在后序的位置,那么从后序开头到这个位置之间就是左子树,这个位置到后序的末尾就是右子树。(如下图)

image.png

22.一位小数num四舍五入:(int)(a+0.5);

把double/float转为int时不会四舍五入,而是取整数部分。

24.不是旅行商环路:(以下条件为或的关系)

(1)存在两个连续的点不可达

(2)初末结点不是同一个

(3)路径未访问all结点

若是旅行商环路~根据是否访问过n+1个结点(源点访问2次)判断是否simple

25.

26.二维的向量定义

创建一个10行5列的int类型的二维向量(即一个向量中元素为向量的向量)

1. vector< vector<int> > b(10, vector<int>(5));        
2. //创建一个10*5的int型二维向量

27.大写转小写两种方法

#include<iostream>
#include<cctype>
int main(){
    char c='A';
    char t=tolower(c);//如果c本身是小写字母也没有关系
    char y=c+32;
    cout<<t<<endl<<y;
    return 0;
}

28.输出每个学校的总分和排名:pres表示前一个学校的加权总分,如果pres和当前学校的加权总分不同说明rank等于数组下标+1,否则rank不变。

struct node{
  string school;
  int tws,ns;//加权总分 参赛人数
};
    sort(ans.begin(),ans.end(),cmp);
  int rank=0,pres=-1;
  //pres表示前一个学校的加权总分
  //如果pres和当前学校的加权总分不同,说明rank等于数组下标+1,否则rank不变
  printf("%d\n",(int)ans.size());
  for(int i=0;i<ans.size();i++){
    if(pres!=ans[i].tws)  rank=i+1;
    pres=ans[i].tws;
    printf("%d ",rank);
    cout<<ans[i].school;
    printf(" %d %d\n",ans[i].tws,ans[i].ns);//加权总分,参赛人数
  }

29.输出string类的字符串s某个字符s[i]的printf的格式为%c

30.找坏键A1112~用散列。注意只要某字符有一次重复出现的个数≠K的倍数,此键算好键。

//字符在计算机中以ASCII码的形式存储,当字符作为数组下标时,其表示的下标值为该字符的ASCII码的十进制值。

附:ASCII码对照表  (使用字符作为下标时,容易发生溢出问题,注意!!)

        string input,output="";
  int K;
  cin>>K>>input;
  //==========处理hashTable===========
  int hashTable[128]={0};//表示是不是坏键
  //下标为字符,元素为1表示该字符是坏键,为-1表示该字符好键,0表示该字符还没遇到过
  for(int i=0;i<input.size();){
    int j=i+1;
    while(j<input.size()&&input[j]==input[i])        
      ++j;//找到i位置后第一个不等于input[i]的字符位置
    if(hashTable[input[i]]>=0)//当前的input[i]是坏键
      hashTable[input[i]]=(j-i)%K==0?1:-1;
    //通过连续出现的input[i]的个数是否是K的倍数给hashTable赋值1、-1
    i=j;
  }

31.n&(n-1)的运用

题目:输出某数的二进制中1的个数,其中负数用补码表示。

    public int NumberOf1(int n) {
        int count = 0;
        while (n!=0) {
            count++;
            n = n & (n - 1);
        }
        return count;
    }

(1)n为奇数(n的二进制表示的末位为1):

n:       xxxxxxxx1

n-1:     xxxxxxxx0

n&(n-1): xxxxxxxx0

相当于去掉最右边的一个1。

(2)n为偶数且不等于0(n的二进制表示的末位为0):

n:       xxxxx1000

n-1:     xxxxx0111

n&(n-1): xxxxx0000

也是相当于去掉最右边的一个1。

32.

经验

(1)上交大佬的总结https://zhuanlan.zhihu.com/p/60841044

(2)CSP题型(5道题)

第一题:水题(稍微有些编程经验就可以写)

第二题:小模拟(处理比较简单的问题,掌握C++STL很有帮助)

第三题:大模拟(处理复杂的问题,一般涉及文本处理,需要熟练掌握C++STL并且细心)

第四题:算法题(难度一般,重点考图论算法和动态规划)

第五题:算法题(难度很高,涉及算法面很多,而且数据量很大,需要对算法极致优化,很难满分)

mark一个b站博主的CSP经验分享(https://www.bilibili.com/video/BV1oK411W7st

相关文章
|
6月前
|
编解码 缓存 算法
【计算机图形学】期末复习,选择题+判断题篇
【计算机图形学】期末复习,选择题+判断题篇
|
存储 SQL 安全
针对国赛知识点总结一
狗蛋师傅投稿,师傅讲:因为最近几年的国赛和各个地方省赛会出一些漏洞复现的题目 师傅整理出来一些笔记给大家看看
686 0
高职考技能提升教程008期 掷骰子与冒泡排序 VB语言 刘金玉编程
高职考技能提升教程008期 掷骰子与冒泡排序 VB语言 刘金玉编程
7-10 排座位 —— 程序设计天梯赛
布置宴席最微妙的事情,就是给前来参宴的各位宾客安排座位。无论如何,总不能把两个死对头排到同一张宴会桌旁!这个艰巨任务现在就交给你,对任何一对客人,请编写程序告诉主人他们是否能被安排同席。
149 0
7-10 排座位 —— 程序设计天梯赛
|
存储 SQL Java
Java面向对象程序设计期末题库(判断题)
Java面向对象程序设计期末题库(判断题)
2610 1
|
Linux
【程序设计天梯赛】L1-1 嫑废话上代码
Linux 之父 Linus Torvalds 的名言是:“Talk is cheap. Show me the code.”(嫑废话,上代码)。本题就请你直接在屏幕上输出这句话。
111 0
|
双11 C语言
【牛客刷题】/*开胃菜——简单四道编程题*/
【牛客刷题】/*开胃菜——简单四道编程题*/
198 0