#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
操作符使用部分
第1题
作业标题
下面代码的结果是:( )
作业内容
#include <stdio.h>
int main()
{
int a, b, c;
a = 5;
c = ++a;
b = ++c, c++, ++a, a++;//逗号','的优先级最低。所以这里b=++c,而不是逗号表达式。//b=7
b += a++ + c;//在这个表达式中,+=优先级最低,后缀++最高。a++ +c: a+c之后,a再++。因此:+ -> ++ a=9
// -> += b=7+(8+8)=23
printf("a = %d b = %d c = %d\n:", a, b, c);
return 0;
}//(B)
A.a = 8 b = 23 c = 8
B.a = 9 b = 23 c = 8
C.a = 9 b = 25 c = 8
/D.a = 9 b = 24 c = 8
第3题
作业标题
交换两个变量(不创建临时变量)
作业内容
不允许创建临时变量,交换两个整数的内容
int main()
{
int a = 20;
int b = 30;
//异或操作符^:相同为0,相异为1
a = a ^ b;//a1=a0^b0
b = a ^ b;//b1=a0^b0^b0=a0
a = a ^ b;//a2=a1^b1=a0^b0^a0=b0
printf("a=%d b=%d\n", a, b);
return 0;
}
第4题 牛客网:JZ15 二进制中1的个数
描述
输入一个整数 n ,输出该数32位二进制表示中1的个数。其中负数用补码表示。
数据范围:
−(2^31)<=𝑛<=(2^31)−1
即范围为 :−2147483648<=𝑛<=2147483647
示例1
输入:
10
返回值:
2
说明:
十进制中10的32位二进制表示为0000 0000 0000 0000 0000 0000 0000 1010,其中有两个1。
示例2
输入:
- 1
返回值:
32
说明:
负数使用补码表示 , - 1的32位二进制表示为1111 1111 1111 1111 1111 1111 1111 1111,其中32个1
int main()
{
int a = 0;
scanf("%d", &a);//2147483647
int b = 1;
int count = 0;
int c = 0;
for (int d = 1; d <= 32; d++)
{
c = a & b;
if (c==b)
{
count++;
}
//printf("c=%d\n", c);
b = b << 1;
}
printf("%d", count);
return 0;
}
用牛客的测试函数
*
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param n int整型
* @return int整型
int NumberOf1(int n) {
// write code here
}
int NumberOf1(int n)
{
int flag = 0x0001;
int i = 0;
int iNum = 0;
for (i = 0; i < 32; i++)
{
iNum += (n & flag);
n = n >> 1;
}
return iNum;
}
int NumberOf1(int n)
{
int flag = 0x0001;
int i = 0;
int iNum = 0;
int c = 0;
for (i = 0; i < 32; i++)
{
/*iNum += (n & flag);
n = n >> 1;*/
c = n & flag;
if (c == flag)
{
iNum++;
}
//printf("c=%d\n", c);
flag = flag << 1;
}
return iNum;
}
标准答案:
(不按牛客网的要求)
void NumberOf1(unsigned int n) {//强制类型转换后,-1对应的原码的符号位变成非符号位,其所对应的数为正数。
int count = 0;
while (n)
{
if (n % 2 == 1)//十进制数转换成二进制数原理:除二取余法
count++;
n = n / 2;
}
printf("%d\n", count);
}
int main()
{
int n = -1;
NumberOf1(n);
return 0;
}
(按牛客网的要求)
int NumberOf1(int n)
{
int i = 0;
int count = 0;
for (i = 0; i < 32; i++)
{
if (((n >> i) & 1) == 1)
{
count++;
}
}
return count;
}
int main()
{
int n = 0;
scanf("%d", &n);
int ret = NumberOf1(n);
printf("%d\n", ret);
return 0;
}
小母牛坐飞机类的代码(效率极高版)
int NumberOf1(int n)
{
int count = 0;
while (n)//n=0时,停止循环。
{
n = n & (n - 1);//n=0之前,循环了多少次,n按位与了多少次,就有多少个1。
count++;
}
return count;
}
int main()
{
int n = 0;
scanf("%d", &n);
int ret = NumberOf1(n);
printf("%d\n", ret);
return 0;
}
第5题
作业标题
打印整数二进制的奇数位和偶数位
作业内容
获取一个整数二进制序列中所有的偶数位和奇数位,分别打印出二进制序列
思路:从右往左数,2n-1位是奇数位,2n位是偶数位:
从左往右数,2n位是奇数位,2n-1位是偶数位。
即最右端首位及每间隔一位为奇数位,其他位为偶数位。
标准答案:
void Print(int n)
{
int i = 0;
//如果从左往右按顺序打印的话,总共需逻辑右移31个数(32-1)。
//其中奇数位首次逻辑右移需30位,每次比上一次少移动2位,最后一次逻辑右移0位,共需16次
printf("奇数位:");
for (i = 30; i >= 0; i -= 2)
{
printf("%d ", (n >> i) & 1);
}
printf("\n");
//其中偶数位首次逻辑右移需31位,每次比上一次少移动2位,最后一次逻辑右移1位,共需16次
printf("偶数位:");
for (i = 31; i >= 1; i -= 2)
{
printf("%d ", (n >> i) & 1);
}
}
int main()
{
int n = 0;
scanf("%d", &n);
Print(n);
return 0;
}
第6题 OR76 两个整数二进制位不同个数
作业标题
求两个数二进制中不同位的个数
作业内容
编程实现:两个int(32位)整数m和n的二进制表达中,有多少个位(bit)不同?
示例1
输入
22 33
输出
5
示例2
输入 :
1999 2299
输出 : 7
void BitwiseAND(int a, int b)
{
int c = a ^ b;
int d = 1;
int count = 0;
//int f = 0;
for(int e=1;e<=32;e++)
{
//f = c & d;
if ((c & d) == d)//if (f == d)
//if (c & d == d)//位与&优先级比==低,因此这样写错误
{
count++;
}
d = d << 1;
}printf("%d", count);
}
int main()
{
int a = 0;
int b = 0;
scanf("%d %d", &a, &b);
BitwiseAND(a, b);
return 0;
}
标准答案①:
int BitwiseAND(int a, int b)
{
int c = 0;
int count = 0;
for(c=1;c<=32;c++)
{
if (((a >> c) & 1) != ((b >> c) & 1))
{
count++;
}
}
return count;
}
int main()
{
int a = 0;
int b = 0;
scanf("%d %d", &a, &b);
int ret = BitwiseAND(a, b);
printf("%d\n", ret);
return 0;
}
标准答案②:
int BitwiseAND(int a, int b)
{
int c = a ^ b;
int count = 0;
while (c)
{
c = c & (c - 1);
count++;
}
return count;
}
int main()
{
int a = 0;
int b = 0;
scanf("%d %d", &a, &b);
int ret = BitwiseAND(a, b);
printf("%d\n", ret);
return 0;
}
第7题
作业标题
BC117 - 小乐乐走台阶=青蛙跳台阶问题=(小乐乐=青蛙)
描述
小乐乐上课需要走n阶台阶,因为他腿比较长,所以每次可以选择走一阶或者走两阶,那么他一共有多少种走法?
输入描述:
输入包含一个整数n(1 ≤ n ≤ 30)
输出描述:
输出一个整数,即小乐乐可以走的方法数。
示例1
输入:
2
输出:
2
示例2
输入:
10
输出:
89
标准答案:
斐波那契数:Fib(n)=Fib(n-1)+Fib(n-2) (n>=3)
=1 (n=1,2)
int Fib(int n)
{
if (n <= 2)
return n;
else
return Fib(n - 1) + Fib(n - 2);
}
int main()
{
int n = 0;
scanf("%d", &n);
int ret = Fib(n);
printf("%d\n", ret);
return 0;
}
第8题
作业标题
BC54 - 获得月份天数
描述
KiKi想获得某年某月有多少天,请帮他编程实现。输入年份和月份,计算这一年这个月有多少天。
输入描述:
多组输入,一行有两个整数,分别表示年份和月份,用空格分隔。
输出描述:
针对每组输入,输出为一行,一个整数,表示这一年这个月有多少天。
示例1
输入:
2008 2
输出:
29
标准答案①:
// 1 2 3 4 5 6 7 8 9 10 11 12
// 31 28(29) 31 30 31 30 31 31 30 31 30 31
int get_days_of_month(int y, int m)
{
int day = 0;
switch (m)
{
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 ((y % 4 == 0) && (y % 100 != 0) || (y % 400 == 0))
day++;
}
break;
}
return day;
}
int main()
{
int y = 0;
int m = 0;
while (scanf("%d %d", &y, &m) == 2)//输入的是两个值,应该判断是否等于2
{
int ret = get_days_of_month(y, m);
printf("%d", ret);
}
return 0;
}
标准答案②(进阶版):
int get_days_of_month(int y, int m)
{
int days[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
// 1 2 3 4 5 6 7 8 9 10 11 12
int day = days[m];
if (((y % 4 == 0) && (y % 100 != 0) || (y % 400 == 0)) && (m == 2))
{
day++;
}
return day;
}
int main()
{
int y = 0;
int m = 0;
while (scanf("%d %d", &y, &m) == 2)//输入的是两个值,则读到的就是两个数,返回值也就是 2,所以要判断是否等于2
{
int ret = get_days_of_month(y, m);
printf("%d", ret);
}
return 0;
}
补充:
输入一个数,判断其是否为2的k次方。
思路:①2的k次方的数字,对应的二进制位原码的表示只有1个1。
②原码n&(n-1)=0的数字必定是2的k次方。
算术转换部分
第1题
作业标题
下面代码的结果是:( A )
#include <stdio.h>
int i;//全局变量不初始化等于0。
int main()
{
i--;
//sizeof计算结果是无符号整数——unsigned int。size_t——是sizeof计算的结果的类型。
//因此,这里i要与sizeof进行比较,则需进行int到unsigned int的算术转换。
//故经算术转换后,i为二进制位全是1的无符号数——(2^32)-1=4294967295
if (i > sizeof(i))
{
printf(">\n");
}
else
{
printf("<\n");
}
return 0;
}
A. >
B. <
C.不输出
D.程序有问题
第3题
作业标题
下面代码的结果是:( D )
#include <stdio.h>
int main()
{
int i = 1;
int ret = (++i) + (++i) + (++i);//不同编译器,不同结果。
printf("ret = %d\n", ret);
return 0;
}
A.10
B.12
C.9
D.程序错误
第4题
作业标题
BC90 - 矩阵计算
作业内容
描述
输入NxM矩阵,矩阵元素均为整数,计算其中大于零的元素之和。
输入描述:
第一行为N M(N: 矩阵行数;M: 矩阵列数, 且M, N <= 10),接下来的N行为矩阵各行。
输出描述:
一行,其中大于零的元素之和。
示例1
输入:
3 3
2 3 4
- 5 - 9 - 7
0 8 - 4
输出:
17
标准答案:
int main()
{
int M = 0;
int N = 0;
scanf("%d %d", &M, &N);
int i = 0;
int j = 0;
int a = 0;
int sum = 0;
for (i = 0; i < M; i++)
{
for (j = 0; j < N; j++)
{
scanf("%d", &a);
if (a > 0)
sum += a;
}
}printf("%d\n", sum);
return 0;
}
第5题
作业标题
BC111 - 小乐乐与进制转换
作业内容
描述
小乐乐在课上学习了二进制八进制与十六进制后,对进制转换产生了浓厚的兴趣。因为他的幸运数字是6,所以他想知道一个数表示
为六进制后的结果。请你帮助他解决这个问题。
输入描述:
输入一个正整数n(1 ≤ n ≤ 109)
输出描述:
输出一行,为正整数n表示为六进制的结果
示例1
输入:
6
输出:
10
示例2
输入:
120
输出:
320
标准答案:
思想:
十进制数转N进制数:
整数部分:除以N,取余,商为0时,余数倒序输出;
小数部分:乘以N,取整,积为0时,整数正序输出。
本题以正整数为例
循环法:
int main()
{
int arr[20] = { 0 };//存储余数,以便打印。
int n = 0;
scanf("%d", &n);
int i = 0;
while (n)//除以N,商为0时,循环结束。
{
arr[++i] = n % 6;//从下标为1的元素开始存储//取余,数组存储余数
n /= 6;
}
for (i; i > 0; i--)//下标为0的元素并没有参与存储余数,而是存储其原本的值//倒序输出余数
{
printf("%d", arr[i]);
}
return 0;
}
递归法:
void Print(int n)
{
if (n > 5)//六进制:逢6进1。
{
Print(n / 6);
}
printf("%d", n % 6);
}
int main()
{
int n = 0;
scanf("%d", &n);
int i = 0;
Print(n);
return 0;
}
第6题
作业标题
【二维数组】BC107 - 矩阵转置
作业内容
描述
KiKi有一个矩阵,他想知道转置后的矩阵(将矩阵的行列互换得到的新矩阵称为转置矩阵),请编程帮他解答。
输入描述:
第一行包含两个整数n和m,表示一个矩阵包含n行m列,用空格分隔。(1≤n≤10, 1≤m≤10)
从2到n + 1行,每行输入m个整数(范围 - 231~231 - 1),用空格分隔,共输入n * m个数,表示第一个矩阵中的元素。
输出描述:
输出m行n列,为矩阵转置后的结果。每个数后面有一个空格。
示例1
输入:
2 3
1 2 3
4 5 6
输出:
1 4
2 5
3 6
标准答案:
int main()
{
int m = 0;
int n = 0;
scanf("%d %d", &m, &n);
int arr[m][n];//变长数组,VS不支持C99标准,因此不能正常使用。牛客网支持。
int i = 0;
int j = 0;
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
{
scanf("%d", &arr[i][j]);//输入矩阵:第m行第n列元素
}
}
for (i = 0; i < n; i++)
{
for (j = 0; j < m; j++)
{
printf("%d ", arr[j][i]);//矩阵转置,输出矩阵:第n行第m列元素
}printf("\n");
}
return 0;
}
第7题
作业标题
BC98 - 序列中删除指定数字
作业内容
描述
有一个整数序列(可能有重复的整数),现删除指定的某一个整数,输出删除指定数字之后的序列,序列中未被删除数字的前后位置
没有发生改变。
数据范围:序列长度和序列中的值都满足1≤n≤50
输入描述:
第一行输入一个整数(0≤N≤50)。
第二行输入N个整数,输入用空格分隔的N个整数。
第三行输入想要进行删除的一个整数。
输出描述:
输出为一行,删除指定数字之后的序列。
示例1
输入:
6
1 2 3 4 5 9
4
输出:
1 2 3 5 9
示例2
输入:
5
1 2 3 4 6
5
输出:
1 2 3 4 6
投机做法(并未真正意义上的删除):
int main()
{
//输入一个整数n
int n = 0;
scanf("%d", &n);
int arr[n];
//输入n个整数
int i = 0;
for (i = 0; i < n; i++)
{
scanf("%d", &arr[i]);
}
//输入删除的数字
int del = 0;
scanf("%d", &del);
for (i = 0; i < n; i++)
{
if (arr[i] == del)
arr[i] = 0;
}
//输出不为0的数字——没被删除过的数字。
for (i = 0; i < n; i++)
{
if (arr[i] != 0)
printf("%d ", arr[i]);
}
return 0;
}
踏实写法(真正意义上的删除):
思路:建立一个数组,将不删除的元素按顺序依次重新放入原数组
即,后面的元素往前覆盖。
int main()
{
int n = 0;
scanf("%d", &n);
int arr[n];
int i = 0;
for (i = 0; i < n; i++)
{
scanf("%d", &arr[i]);
}
int del = 0;
scanf("%d", &del);
//删除,并把不删除的元素按原有顺序依次重新放回原数组,对删除元素进行覆盖。
int j = 0;
for (i = 0; i < n; i++)
{
if (arr[i] != del)
arr[j++] = arr[i];
}//循环结束时j=j+1
//打印:此时数组元素只有j个元素
for (i = 0; i < j; i++)
{
if (arr[i] != 0)
printf("%d ", arr[i]);
}
return 0;
}