判断闰年: 判断某个年份是不是闰年,如果是闰年,请输出yes,否则请输出no
输入: 一行,只有一个整数x (0<=x <=10000)
输出: 只有一行字符
闰年: 1.年份能被4整除并且不能被100整除 2.年份能被400整除
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 # define _CRT_SECURE_NO_WARNINGS #include <stdio.h> int main() { int year = 0; scanf("%d", &year); if (year % 400 == 0 || (year % 4 == 0 && year % 100 != 0)) { printf("yes"); } else { printf("no"); } return 0; }
判断回文数 输入一个整型数,判断是否是对称数,如果是,输出yes,否则输出no,不用考虑这个整型数过大,int类型存不下,不用考虑负值;
例如 12321是对称数,输出yes,124421是对称数,输出yes,1231不是对称数,输出no
原数 == 反转后的数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 # define _CRT_SECURE_NO_WARNINGS #include <stdio.h> int main() { int i = 0; int i2 = 0; int tmp = 0; scanf("%d", &i); i2 = i; while (i) { tmp = tmp * 10 + i % 10; i = i / 10; } if (tmp == i2) { printf("yes"); } else { printf("no"); } return 0; }
逆转字符串 读取一个字符串,字符串可能含有空格,将字符串逆转,原来的字符串与逆转后字符串相同,输出0,原字符串小于逆转后字符串输出-1,大于逆转后字符串输出1。例如输入 hello,逆转后的字符串为 olleh,因为hello 小于 olleh,所以输出-1
输入一个字符串,例如 hello,当然输入的字符串也可能是 how are you,含有空格的字符串
输出是一个整型数,如果输入的字符串是hello,那么输出的整型数为-1
键盘输入的字符串,系统会自动加上 ‘\0’
自定义的字符串需要手动加上 ‘\0’ 表示字符串结尾
strcspn(char *str1,char *str2)
str c spn [c -> complement(补集,不包含),spn ->span(连续长度)]
函数返回str1 开头连续n个字符都不含字符串str2 内字符的字符数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 # define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <string.h> int main() { char input[100]; fgets(input, 100, stdin); input[strcspn(input, "\n")] = '\0'; // 去掉换行 char output[100]; for (int i = 0; i < strlen(input); i++) { output[i] = input[strlen(input) -1-i]; } output[strlen(input)] = '\0'; /*fputs(output, stdout); printf("\n");*/ int result = strcmp(input, output); if (result < 0) { printf("%d\n", -1); } else if (result > 0) { printf("%d\n", 1); } else { printf("%d\n", 0); } return 0; }
如果不去掉 input的’\n’,那么’\n’也会跟着被反转
换钞票 某人想将手中的一张面值100元的人民币换成10元、5元、2元和1元面值的票子。要求换正好40张,且每种票子至少一张。问:有几种换法?
循环结构的嵌套
注: “= ”是赋值,“== ”是关系运算符
题目有两个限制:
钱的总张数 = 40
每张票子都得有
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 # define _CRT_SECURE_NO_WARNINGS #include <stdio.h> //换货币 int main() { int result = 0; int count = 0; // 要求换正好40张 // 100 换成 10,5,2,1 int k = 0; int m = 0; int j = 0; int s = 0; for (k = 1; k < 11; k = k + 1) { /*result = k * 10 + m * 5 + j * 2 + s * 1;*/ for ( m = 1; m < 21; m = m + 1) { //result = k * 10 + m * 5 + j * 2 + s * 1; for ( j = 1; j < 51; j = j + 1) { //result = k * 10 + m * 5 + j * 2 + s * 1; for ( s = 1; s < 101; s = s + 1) { result = k * 10 + m * 5 + j * 2 + s * 1; // 赋值运算符 if (result == 100 && (k+m+j+s == 40)) { count ++; } } } } } printf("%d", count); return 0; }
枚举思想(暴力法)
面对一个问题时,直接将问题的所有可能性全部列出,一个一个的去检查是否符合题目的要求
故 枚举思想的核心便是用 循环结构 (for,while)去解决问题
找完数
完数是指除本身以外的因子之和等于其本身的数。
任给一个自然数n,求n以内的所有完数。如果找不到,则输出”No”
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 # define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <string.h> int main() { // 找完数 int n = 0; scanf("%d", &n); if (0 < n < 10000) { // 逐个循环 for (int k = 1; k < n + 1; k++) { //找单个的因子 int sum = 0; for (int i = k - 1; i > 0; i--) { if (k % i == 0) { sum += i; } } if (sum == k) { printf("%d\n", k); } } } else { printf("输入值有误,请输入 0-10000 之间的值"); } return 0; }
水仙花数
“水仙花数”是指一个三位数,其各位数字的立方和等于该数本身。例如,153是一个水仙花数,因为 1³ + 5³ + 3³ = 153。
请编写程序,找出所有的三位水仙花数。
注意: pow(i,3) 函数的返回值是 double 数据类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 # define _CRT_SECURE_NO_WARNINGS #include <stdio.h> int main() { int m = 0; for (int i = 1; i < 10; i++) { for (int k = 0; k < 10; k++) { for (int j = 0; j < 10; j++) { m = i * 100 + k * 10 + j; if (i*i*i + j * j * j + k * k * k == m) { printf("%d\n", m); } } } } return 0; }
分治思想
无法从全局解决问题,那就从局部解决问题,这便是分治法(分而治之)
大问题转移到小问题,小问题有解决方法
爬楼梯 假设你正在爬一个楼梯。它总共有n 阶台阶,每次你只能爬 1 阶,或者爬 2 阶
问:你有多少种不同的方法可以爬到楼顶
num为 n 的数量 = num 为 n-1 的数量 + num 为 n-2 的数量
当n >2 时,最后一步要么跨1个台阶,要么跨2个台阶,两者互斥
逐级往下分
假设n = 5,f(5) = f(3) 【最后一步跨两个台阶】+ f(4)【最后一步跨一个台阶】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 # define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <string.h> int f(int n) { if (n > 2) { int result = f(n - 1) + f(n - 2); return result; } else if(n == 2){ return 2; } else if (n == 1) { return 1; } } int main() { int n = 4; printf("%d", f(n)); return 0; }
汉诺塔问题 有 n 个从小到大排列的圆盘,需要将圆盘全部就移动到另一个柱子上,并遵守:
每次只能移动一个圆盘
移动过程中,大盘不能放在小盘上面
只能移动最顶端的圆盘
大问题:
将上面的 前 n-1 个盘子 从 A移动到B
将下面的 n 个盘子从 A移到 C
将 n-1 个盘子从 B移到 C
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 # define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <string.h> void hanoi(int n, char from, char buffer, char to) { if (n > 1) { //前 n - 1个圆盘 从 from 到 buffer hanoi(n - 1, from, to, buffer); // 第n 个盘子从 form 到 to hanoi(1, from, buffer, to); // 前 n - 1个圆盘 从 buffer 到 to hanoi(n - 1, buffer, from, to); } else if (n == 1) { printf("move %c to %c\n", from, to); } } int main() { int n = 4; hanoi(n, 'A', 'B', 'C'); return 0; }
归并排序 对一个无序数组,进行排序
大问题转移成小问题;
左侧和右侧分别是有序的数组后进行合并
小问题:
当数组只有 1 个元素的时候(left == right)数组字然有序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 # define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <string.h> // 归并排序 void merge(int* arr, int* temp, int left, int right, int mid) { // 将 arr 的内容备份到 tmp中 for (int i = left; i <= right; ++i) { temp[i] = arr[i]; } // i访问左半边,j访问右半边,k存放结果 int i, j, k; for (i = left, j = mid + 1, k = left; i <= mid && j <= right; ++k) { if (temp[i] < temp[j]) { arr[k] = temp[i]; ++i; } else { arr[k] = temp[j]; ++j; } } while (i <= mid) { arr[k] = temp[i]; ++i; ++k; } while (j <= right) { arr[k] = temp[j]; ++j; ++k; } } void mergeSort(int* arr, int* temp, int left, int right) { if (left < right) { int mid = (left + right) / 2; mergeSort(arr, temp, left, mid); mergeSort(arr, temp, mid + 1, right); merge(arr, temp, left, right, mid); } } int main() { int arr[] = { 6,5,9,8,2,3,4,7,10,1 }; int temp[10]; mergeSort(arr, temp, 0, 9); return 0; }
C++引用 c++ 的引用本质是为变量起了一个外号,在子函数中可以直接操作主函数变量
编译器需要改成 c++ 环境下
注: & 在不同的位置,不同的语境下,功能完全不同
在类型后面是外号(引用 )char* &p_ref;
在变量前面是地址(取地址 )&a,c++的引用;
在两数中间是计算(位运算 )a & b
使用C++的引用,注意提交时把代码选为C++;在主函数定义字符指针 char *p,然后在子函数内malloc申请空间(大小为100个字节),通过fgets读取字符串,然后在主函数中进行输出;要求子函数使用C++的引用,注意在C++中从标准输入读取字符串,需要使用fgets(p,100,stdin)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 # define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <string.h> // char* &p 代表 p 是 main 函数里指针变量的别名 void func(char*& p) { p = (char*)malloc(100); fgets(p, 100, stdin); } int main() { char* p = NULL; func(p); if (p != NULL) { printf("%s", p); free(p); } return 0; }
scanf() 输出格式: scanf() 中的 %c 不会忽略空白字符,故%c 会将空格符认为是输入
解决方法是:在“ %c” 前面加上空格,让其忽略空白字符
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 # define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct student_s { int id; char name[20]; char gender; }student_t; int main() { student_t student; scanf("%d %s %c",&student.id,student.name,&student.gender); printf("%d %s %c", student.id, student.name, student.gender); return 0; }