天天看点

C语言刷题(1)

1、判断n是不是2的k次方

分析:
C语言刷题(1)

知识点:

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、获取一个整数二进制序列中所有的偶数位和奇数位,分别打印出二进制序列

分析:
C语言刷题(1)

 知识点:

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的每一位是否不相等

分析:
C语言刷题(1)
#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;
}
           

运行结果:

C语言刷题(1)

 代码2:借助异或操作符和tmp=tmp&(tmp-1)

分析:
C语言刷题(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:递归

分析:
C语言刷题(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:迭代

分析:
C语言刷题(1)

 知识点:

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开关语句

分析:
C语言刷题(1)

 知识点:

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:数组存储月份的天数

分析:
C语言刷题(1)
 知识点:数组的下标是从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;
}
           

继续阅读