1、判断n是不是2的k次方
分析:
知识点:
1、2的k次方的整数,2进制的表示中只有1个1。
2、每执行一次n=n&(n-1),就会去掉n二进制中的1个1。
3、位操作符:
(1)运算规则:
①&——按(二进制)位与,对应的二进制位:有0则0,两个同时为1才为1
②|——按(二进制)位或,对应的二进制位:有1则1,两个同时为0才为0
③^——按(二进制)位异或,对应的二进制位:相同为0,相异为1
(2)按位异或的性质:
①a^a=0
②a^0=a
③支持交换律:a^a^b=a^b^a=b
代码实例:
#include<stdio.h> int main() { int n = 0; //输入 scanf("%d", &n); //判断n是否为2的k次方 if ((n & (n - 1)) == 0) { printf("%d是2的k次方\n", n); } else { printf("%d不是2的k次方\n", n); } return 0; }
2、获取一个整数二进制序列中所有的偶数位和奇数位,分别打印出二进制序列
分析:
知识点:
1、想要获取一个数的每一位,我们的思想是把高位的数变成低位来获取,因为低位的数更易获取
2、想得到一个数二进制的最低位的操作:n&1
3、二进制高位变低位:通常使用右移操作符
4、<<左移操作符
移位规则:
①左边抛弃,右边补0
5、>> 右移操作符
移位规则:
①(常见如VS)算术右移:左边补原来的符号位,右边抛弃
②逻辑右移:左边直接补0,右边抛弃
6、移位操作符虽然产生了二进制的移动,但是实际上变量n在没有被赋值的情况下,自身的值不会发生变化
代码实例:
#include<stdio.h> //自定义函数——实现打印一个整数二进制序列中所有的偶数位和奇数位,分别打印 void print(int n) { //循环变量 int i = 0; //提示 printf("奇数位:"); //打印二进制序列中所有奇数位 for (i = 30; i >= 0; i -= 2) { printf("%d ", (n >> i) & 1); } //换行 printf("\n"); //提示 printf("偶数位:"); //打印二进制序列中所有偶数 for (i = 31; i >= 1; i -= 2) { printf("%d ", (n >> i) & 1); } //换行 printf("\n"); } int main() { int n = 0; //输入 scanf("%d", &n); //调用函数,打印n二进制序列中的奇数位和偶数位 print(n); return 0; }
3、求两个数二进制中不同位的个数
代码1:判断m和n的每一位是否不相等
分析:
#include<stdio.h> //自定义函数——实现求两个数二进制中不同位的个数 int count_diff_one(int m, int n) { int count = 0;//计数器 int i = 0;//循环变量 //循环32次每一次判断m,n中是否不同位,不同位加1 for (i = 0; i < 32; i++) { if (((n >> i) & 1) != ((m >> i) & 1)) { count++; } } return count; } int main() { int n = 0; int m = 0; //输入 scanf("%d %d", &n, &m); //调用函数,求两个数二进制中不同位的个数 int ret = count_diff_one(m, n); //输出不同位的个数 printf("%d\n", ret); return 0; }
运行结果:
代码2:借助异或操作符和tmp=tmp&(tmp-1)
分析:
#include<stdio.h> //自定义函数——实现求两个数二进制中不同位的个数 int count_diff_one(int m, int n) { int count = 0;//计数器 int tmp = m ^ n;//运算规则:相同为0,相异为1 //统计tmp的二进制有几个1 while (tmp) { tmp = tmp & (tmp - 1);//执行一次,就会去掉tmp二进制中的一个1 count++; } return count; } int main() { int n = 0; int m = 0; //输入 scanf("%d %d", &n, &m); //调用函数,求两个数二进制中不同位的个数 int ret = count_diff_one(m, n); //输出不同位的个数 printf("%d\n", ret); return 0; }
4、BC117-小乐乐走台阶
点击题目链接,做题
代码1:递归
分析:
知识点:
1、什么是递归?
程序调用自身的编程技巧称为递归。(即一个函数在其定义中有直接或间接调用自身的一种方法)
2、递归的思想:
递归主要思考的方式在于:大事化小
3、递归的作用:
递归策略,只需少量的程序就可描述解题过程所需要的多次重复计算,大大减少了程序的代码量
4、递归的理解:
递归要分开理解:递--->递推,归--->回归。先递推再回归。
5、递归的两个必要条件:
①存在限制条件,当满足这个限制条件的时候,递归便不继续了(递归出口)
②每次递归调用之后越来越接近这个限制条件
6、递归与迭代,当递归存在如下问题时,优先用迭代:
①递归层次太深时,栈溢出程序会崩溃
②递归的过程中有很多计算在一直重复时,程序效率低
#include <stdio.h> long int Fib(int n) { if (n <= 2) { return n; } else { return Fib(n - 1) + Fib(n - 2); } } int main() { int n = 0; //输入n scanf("%d", &n); //调用函数——递归实现有多少走法 long int ret = Fib(n); //输出 printf("%d\n", ret); return 0; }
代码2:迭代
分析:
知识点:
1、迭代(非递归):循环就是一种迭代,迭代可以理解成循环。
long int Fib(int n) { int a = 1; int b = 2; long int sum = 0; if (n <= 2) { sum = n; } for (int i = 3; i <= n; i++) { sum = a + b; a = b; b = sum; } return sum; } int main() { int n = 0; //输入n scanf("%d", &n); //调用函数——迭代实现有多少走法 long int ret = Fib(n); //输出 printf("%d\n", ret); return 0; }
5、BC54-获得月份天数
点击题目链接,做题
代码1:switch开关语句
分析:
知识点:
1、关于月份求月份天数的题目:
①要注意是否为二月
②该年是否为闰年
2、判断闰年的条件:
①四年一闰,百年不闰:能被4整除,并且不能被100整除
②每四百年再一闰:能被400整除
3、月大月小口诀:一月大,二月平,三月大,四月小,五月大,六月小,七月大,八月大,九月小,十月大,十一月小,十二月大。
4、switch语句的功能:当表达式的内容与某个case标签后的常量相等后,就执行该case下的语句,break表示该case以后的内容不会执行,如果没有跟break,会继续执行当前case之后的case分支。
5、switch语句中的break:
①作用:在switch语句中,我们没有办法直接实现分支,搭配break使用才能实现真正的分支。
②不是所有的case后面都要加break,视情况而来。如多个case共用一组执行语句时,共用的执行语句写在最后一个case,其余可省略。
6、switch语句中的default子句:
①功能:当表达式的值与所用case标签的值都不匹配时,这个default子句就会执行。(注:每个switch语句中只能出现一条default子句)
②虽然default子句可以出现在switch中的任意位置,但是建议放在最后。(习惯上我们前面处理正确的,后面处理异常的)
③虽然不加default子句,switch语句也是对的,但是每个switch语句中都放一条default子句是个好习惯,甚至可以在后面再加一个break。
int get_days_of_month(int year, int month) { int day = 0; switch (month) { case 1: case 3: case 5: case 7: case 8: case 10: case 12: day = 31; break; case 4: case 6: case 9: case 11: day = 30; break; case 2: { day = 28; if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) { day++; } } default: break; } return day; } int main() { int year = 0; int month = 0; //多组输入year,month while ((scanf("%d %d", &year, &month)) == 2) { //调用函数——求这一年这个月有几天 int day = get_days_of_month(year, month); //输出 printf("%d\n", day); } return 0; }
代码2:数组存储月份的天数
分析:
知识点:数组的下标是从0开始的
int get_days_of_month(int year, int month) { int day = 0; int days[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 }; day = days[month]; if (month == 2 && (year % 4 == 0 && year % 100 != 0 || year % 400 == 0)) { day++; } return day; } int main() { int year = 0; int month = 0; //多组输入year,month while ((scanf("%d %d", &year, &month)) == 2) { //调用函数——求这一年这个月有几天 int day = get_days_of_month(year, month); //输出 printf("%d\n", day); } return 0; }