题库详解

目录

 

1、输出最长的名字

一个班级中有n个学生,每个学生有一个名字。班主任希望知道学生中名字最长(名字中的一个空格长度计为1)的学生是谁。

输入格式
程序接受的输入的第一行是一个整数n,表示学生的总数。之后的n行,每行会接受一个学生的名字(可能有空格)。学生的名字不超过100个字符。

输出格式
输出n位学生中最长的学生名字(如果有多个名字一样长的学生,输出第一个。

样例输入
3
steve Jobs
Masunny
Fei

样例输出
steve Jobs

#include <stdio.h>
#include <string.h>
int main() 
{
    int n;
    scanf("%d\n", &n);
    char arr[n][100];
    for(int i = 0;i < n;i++)
    {
        for(int j = 0;j < 100;j++)
        {
            scanf("%c",&arr[i][j]);
            if(arr[i][j]=='\n')
            {
                break;
            }
        }
    }
    
    for(int k=0;k<1;k++)
    {
        for(int p=0;p<n-1;p++)
        {
            if(strlen(arr[0])<strlen(arr[p+1]))
            {
                strcpy(arr[0],arr[p+1]);
            }
        }
    }
    for(int i =0;i<strlen(arr[0]);i++)
    {
         if(arr[0][i] == '\n')
         {
             break;
         }
        else
        {
            printf("%c",arr[0][i]);
        }
    }
    return 0;
}
  • 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

2、新哈希函数

一个哈希函数将一个长度为k的字符串转成长度为32的字符串。这个哈希函数f的设计如下:
·声明一个长度为32的数组arr,并将其中元素全部初始化为0。
·取出每一位的ASCIl值,将长度为k的字符串中第i位的ASCIl码加入到 arr[i % 32] 中 ( 1 ≤ i ≤ k )。
·声明一个长度为32的数组bits,令bits[j]为arr[31 - j ]与 arr[ j ] <<1 的值进行了按位异或运算后得到的结果( 0 ≤ j ≤ 31)。
·计算出 bits[ j ] % 85 + 34并将该十进制数在ASCIl码中对应的字符输出到结果字符串的第 j+1位( 0 ≤ j ≤ 31) 。

实现一个程序,当输入一个字符串s后,输出哈希图数的结果f(s)。

输入格式
输入为一行,包括一个长度为k的字符串(32< k < 500),这个字符串由大写字母、小写字母和数字组成(不含空格)。

输出格式
输出为一行,为一个长度为32的字符串哈希结果

样例输入
123456789012345678981234567890123

样例输出
"p*+,)&'ebst*+,)&'ebst*+,)&'eb&r

#include <stdio.h>
int main() 
{
    int arr[32] = {0};
    int bits[32];
    int j, k;
    char m;
    char string[501];
 
    scanf("%s", string);
    k = strlen(string);
    for (j = 0; j < k; j++){
        arr[(j + 1) % 32] += string[j];
    }
 
    for (j = 0; j < 32; j++){
        bits[j] = arr[31 - j] ^ (arr[j] << 1);
    }
 
    for (j = 0; j < 32; j++){
        printf("%c", bits[j] % 85 + 34);
    }
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

3、权限的修改

在Linux操作系统中文件的权限可以通过rwx 的方式来表示,r表示可读,w表示可写,x表示可执行。

在操作系统实现这个功能时,采用的方式是按位存储的。当不给任何权限时,存储表现为三个二进制位0,如果可读则第一位会变成1、如果可写则第二位会变成1、如果可执行则第三位会变成1。例如
·如果可读、可写、可运行,就表示为二进制的111,转换成十进制就是7。
·如果可读、可写、不可运行,就表示为二进制的110,转换成十进制就是6。
·如果可读、不可写、可运行,就表示为二进制的101,转换成十进制就是5。

在这题中,会得到文件当前的权限和希望添加或删除的权限(如果已经对存在/不存在的权限添加/删除则不做改变)。需要输出最终改变后的权限的十进制描述。

输入格式
输入第一行是当前的文件权限,用r、w、x的字母中的一个或多个来表示( r,w,x 不会重复)。之后每一行会以+或·开头;如果以+开头,则表示添加一个权限,如果-开头,则表示删除一个权限。

输出格式
将修改后的权限以十进制数字的方式输出出来。

样例输入1
rw
+x
样例输出1
7

#include <stdio.h>
#include <string.h>
int main() {
    char jur[3];
    char ar[2];
    int num = 0;
    scanf("%s", jur);
    //先对当前的权限进行转换成数值。相当于加权限=加法运算:r=4,w=2,x=1
    for(int i = 0; i < 3; i++){
            if(jur[i] == 'r'){
                num = num + 4;
            }else if(jur[i] == 'w'){
                num = num + 2;
            }else if(jur[i] == 'x'){
                num = num + 1;
            }
        }
    
    //进行权限修改的部分
    //加权限就是加法运算
    //减权限,这里用到的是对二进制的第几位进行置零的操作
    while(scanf("%s", ar) != EOF){
        if(ar[0] == '+'){            //加权限
            if(ar[1] =='r'){
                num = num + 4;
            }else if(ar[1] == 'w'){
                num = num + 2;
            }else if(ar[1] == 'x'){
                num = num + 1;
            }
        }else if(ar[0] == '-'){     //减权限
             if(ar[1] == 'r'){
                num &= ~(1 << 2);
            }else if(ar[1] == 'w'){
                num &= ~(1 << 1);
            }else if(ar[1] == 'x'){
                num &= ~(1 << 0);
            } 
        }  
        getchar();
    }
    printf("%d\n", num);
    
    return 0;
}
  • 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

4、欧几里得算法

求最大公因式

#include <stdio.h>

int gcd(int a, int b)
{
    return (b ? gcd(b, a % b): a);
}

int main()
{
    int a, b;
    while (scanf("%d%d", &a,&b)) 
    {
        printf("gcd(%d,%d)= %din" , a, b, gcd(a, b));
    }
    return 0;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

拓展的欧几里得算法:

#include <stdio.h>
int ex_gcd(int a, int b, int *x,int *y)
{
    if (!b)
    {
        *x = 1,*y = 0;
        return a;
    }
    int xx, yy, ret = ex_gcd(b, a % b, &xx,&yy );
    *x = yy;
    *y = xx - a / b * yy ;
    return ret;
}
int main()
{
    int a, b, x, y;
    while (scanf("%d%d", &a,&b) != EOF) 
    {
        printf("ex_gcd(%d,%d) = %d\n", a,b, ex_gcd(a,b,&x,&y));
        printf("%d * %d+ %d* %d= %d\n", a,x, b, y, a * x + b * y);
    }
    return 0;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

5、素数筛代码

描述:
1、标记一个范围内的数字是否是合数,没有被标记的则为素数
2、算法的空间复杂度为O(N),时间复杂度为o(N * loglogN)
3、总体思想是用素数去标记掉不是素数的数字,例如 i 是素数,那么2i、3i、4*i……就都不是素数

步骤:
1、用prime[ i ]来标记 i 是否是合数
2、标记为1的数字为合数,否则为素数
3、第一次知道2是素数,则将2的倍数标记为1
4、向后找到第一个没有被标记的数字 i
5、将 i 的倍数全部标记为合数
6、重复4–6步,直到标记完范围内的所有数字

#include <stdio.h>
#include <inttypes.h>
#define MAX_RANGE 10000                 //求出10000以内的素数

int prime[MAX_RANGE + 5]={[0};      //初始值为0,代表没有被标记成合数

int main() 
{
    for (int  i = 2; i*i<= MAX_RANGE; i++) 
    {
        if (!prime[i])                  // i没有被标记过,说明i是素致
        {    
            for (int j=2*i; j <= MAX_RANGE; j += i)      //枚举i的倍数
            {
                prime[j]=1;             //将i的倍数标记为1,说明其是合数
            }
        }
    }
    int n;
    while (scanf("%d",&n) != EOF) 
    {
        printf("%s\n", prime[n] == 0 ? "YES" :"NO"); //如果n是素敢,输出YES,香则输出NO
    }
    return 0;
}
  • 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
#include <stdio.h>
#define max_n 100

int prime[max_n + 5]={0};
void init()
{
    for (int i =2; i<=max_n;i++)
    {
        if (prime[i]) continue; //?
        prime[++prime[0]] = i;  //?
        for(int j = i*i;j<=max_n;j += i)
        {
             prime[j] = 1;
        }
    }
    return ;
}

int main() 
{
    init();
    for (int i = 1; i <= prime[0]; i++)
    {
        printf("%d\n", prime[i]);
    }
    printf("prime[0] = %d\n",prime[0]);
    return 0;
}
  • 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

输出:
在这里插入图片描述
prime[++prime[0]] = i;
等价于
int cnt;
cnt = cnt + 1;
prime[cnt] = i;

6、用异或交换两个数

#include <stdio.h>
int main()
{
    int a = 7, b = 3, c;
    a += 7;
    int *p = &a;
    (*p)--;
    printf("a = %d, b = %d\n", a, b);
    a ^= b;    //等价于 int temp = a;
    b ^= a;    //       a = b;
    a ^= b;    //       b = temp;
    printf( "swap : a = d , b = %d \n", a, b);
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

异或存在的一些特点:
a ^ b=c也可以表示为a ^ c=b、b ^ c=a

在此处使用三个异或完成交换可以这样理解:
a ^= b 为 a = a ^ b 可视为 a’ = a ^ b
b ^= a 为 b = b ^ a 也就是 b = b ^ a’ = b ^ a ^ b = a ,此时已将a的值赋给b了
同理a ^= b 为 a = a ^ b 也就是 a = a ^ b = a ^ b ^ a = b ,此时已将b的值赋给a了

7、循环读入

方法一:

#include <stdio.h>
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        printf("n=%d\n",n);
    }
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

方法二:

#include <stdio.h>
int main()
{
    int n;
    while((scanf("%d",&n)) != EOF)
    {
        printf("n=%d\n",n);
    }
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

等价于

#include <stdio.h>
int main()
{
    int n;
    while((scanf("%d",&n)) != -1)
    {
        printf("n=%d\n",n);
    }
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

8、回文数字

#include <stdio.h>

int rev_num(int n, int base)
{
    if (n < 0) return 0;
    int x = n,temp = 0;
    while (x)
    {
        temp = temp * base + x % base;
        x /= base;
    }
    return temp -= n;
}

int main()
{
    int n;
    scanf("%d"",&n);
    printf("%s\n", rev_num(n,10)?"YES":"NO" );  // 10为base的实参
    int x = n,digit = 0;
    do     // 判断输入值是几位数                 
    {
        x /= 10;
        digit += 1;
    }while (x);
    printf("%d has %d digits!\n", n, digit);
    return 0;
}

  • 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

【 rev_num ( n ) ? " YES " : " NO "】意思是:如果rev_num ( n ) 的返回值为1则输出yes,为0则输出no

翻转回文数字并将值存到temp中:【 temp = temp * 10 + x % 10;x /= 10;】可以举个例子123翻转尝试一下

9、高效代码

(1)

#define likely (x)  __builtin_expect ( !!(x) , 1 )   //likely 代表x经常成立
#define unlikely (x)  __builtin_expect ( !!(x) , 0 )    //unlikely代表x不经常成立
  • 1
  • 2

在这里插入图片描述
(2)
想要输出几个数字1 2 3 4 5,第一个数字前面没有空格,后面数字前面都有空格

for(int i=0,i<5,i++)
{
    if(i)     // 看这里
    {
        printf(" ");
    }
    printf("%d",i);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
if ( i != 0)  printf(" "); 
//等价于
if ( i ) printf(" ");       //if(表达式)表达式的值为1后面的程序执行,若为0则不执行。
//又等价于
i && printf(" ");
//还等价于
i == 0 || printf(" ");      //逻辑与运算中i值不为0才可以进行下面,逻辑或前面已成立则不执行后面     
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

if(表达式)表达式的值为1后面的程序执行,若为0则不执行。

逻辑与运算中i值不为0才可以进行下面,逻辑或前面已成立则不执行后面

(3)

#include<stdio.h>
int main()
{
    int a = 0,b = 0;
    if((a++)&&(b++))
    {
        printf("true\n");
    }
    else
    {
        printf("false\n");
    }
    printf("a=%d,b=%d\n",a,b);
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

运行结果为false以及a=1,b=0

在逻辑与的运算中存在一种短路原则,if判断初a++是先赋值后加,因此先赋值a=0,则逻辑与后面不看此结果的值都为0了,因此输出false。后面打印时,a已经赋值操作完毕,因此后加输出为1,而b在前面就没有被执行,因此输出仍为原始值0

(4)

#include<stdio.h>
#include<stdlib.h>    // rand(),srand()所在头文件
#include<time.h>      // time(0)所在头文件

int main()
{
    int n, cnt = 0;
    srand(time(0));   // 让每次产生的随机数都不一样
    scanf("%d",&n);
    for (int i = 0; i < n; i++) 
    {
        int val = rand() % 100;     // 产生随机数
        cnt += (val & 1);           // 统计奇数或偶数的个数
        i && printf(" ");
        printf(""%d", val);
    }
    printf("\n");
    printf( "odd num : %din", cnt);
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
// 统计奇数或偶数的个数
if(val % 2) cnt += 1;
//等价于
if(val & 1) cnt += 1;
//又等价于
cnt += (val & 1);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

10、输出一定数量的偶数

给定一个起始值begin,及一个整数n,输出begin之后(可包含begin)的n个偶数
输入格式:
一行,两个整数,第一个整数对应着起始数字begin,第二个整数对应着将要输出的偶数的个数。
输出格式:
若begin为奇数,则从begin + 1输出,共输出n个偶数;
若begin为偶数,则从begin开始输出,输出n个偶数;
若begin为负数,则从第一个偶数开始输出;
每个偶数输出占一行,0为第一个偶数

#include<stdio.h>
int main()
{
	int begin,n;
	scanf("%d %d",&begin,&n);
	if(begin < 0 ) begin = 0;
	begin += ( begin & 1);     //begin & 1 等价于 begin % 2
	while(n--)
	{
		printf("%d\n",begin);
		begin += 2;
	 }
	return 0;
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值