于航特训课:第一课

passion27 passion27     2022-10-24     544

关键词:

主办单位

      蓝桥杯全国软件和信息技术专业人才大赛组委会

课程时间

      3月4号-3月31

特训内容

  • 7次算法课,大赛特邀专家精讲历届真题及高频算法
  • 直至赛前,资深算法老师群内作业辅导和答疑
  • 全国参赛小伙伴互助带打
  • 第2次课《递归原理与构造技巧》开课时间:2018年3月7日晚上7:30

 

【课程简介】

    《2018蓝桥杯大赛算法特训》是应广大考生需求,由蓝桥杯全国软件和信息技术专业人才大赛组委会主办,聘请大赛资深顾问专家团成员之一于航老师,通过“图文+音视频”多媒体形式提供的蓝桥杯真题常见算法课程,同时还有持续至赛前的微信群作业和辅导答疑。本次课程提供回放。

【课程目标】

      课程通过7次课共14课时深入浅出的讲解,帮助学生快速理解和掌握蓝桥杯大赛中常见的算法思维、算法技能和解题思路。同时提供持续至赛前的微信群内作业及辅导答疑,帮助学生提高学习效率、锻炼算法思维。

【课程大纲】

1、暴力破解与实用性优先

  • 暴力破解在大赛及企业应用中的重要性
  • 暴力破解中的实用性原则
  • 逆向解法
  • 枚举法

2、递归原理与构造技巧

  • 递归的重要性
  • 递归与循环的关系
  • 递归的构造技巧
  • 递归出口的考虑
  • 参数设计
  • 间接递归

3、典型问题的递归框架

  • 排列问题
  • 组合计数问题
  • 组合枚举问题
  • 递归设计——条条大路通罗马

4、数学知识的运用

  • 并非数学竞赛
  • 进制问题及其巧妙运用
  • 整数与整除问题
  • 欧几里得扩展定理
  • 有理数表示,大数问题

5、博弈问题的思路

  • 递归搜索的基本框架
  • 当有平局时的考虑
  • 尼姆定理
  • 缓存结果

6、分治法与动态规划

  • 分治思想的重要性
  • 二分法是基础
  • 动态规划问题的求解次序
  • 复杂问题的规划

7、图及其他

  • 图与树的关系和转化
  • 图的基本遍历
  • 利用树的性质
  • 线段树与并查集介绍

技术分享图片

 


【关于讲师】

      于航

      中科院计算所
      曾于浙江大学电机系实验室、浙大网新、神州泰岳、中科院计算所等从事软件开发或软件技术培训工作,曾在嘉兴电力、福建电信、扬州联通、中石油物探、中国气象局卫星中心等大中型项目中担任项目组长或技术主管。
从第一届蓝桥杯大赛开始至今,作为大赛顾问专家团成员之一,为大赛提供软件开发技术方面的顾问支持,对蓝桥杯大赛有着深刻的影响和了解。
于老师授课风格轻松幽默,对复杂技术难题理解透彻,讲解深入浅出、层次清晰,喜欢以创新的方式呈现问题关键所在。


【购买须知】
  1. 该课程为付费系列课程,按课程计划定期更新,每节课程可在开课时直播学习,也可反复回听
  2. 购买课程后,请确认您是否已添加小蓝为微信好友,然后私聊小蓝,小蓝将您邀请进入微信算法特训学习群。每次开始上课之前,小蓝会在群里提醒您准备上课
  3. 该课程为虚拟内容服务,购买成功后概不退款,敬请原谅
  4. 如有其它疑问,可点击左下角“咨询”按钮,与客服沟通后再购买

1. 如果您在报名过程中遇到问题,请点我寻找答案。

2. 如果还不能解决您的问题,请直接问小蓝。


【往期活动】

 

蓝桥杯算法特训第一课【实用性原则】源代码

技术分享图片

【内容简介】
本文章内容为【2018蓝桥杯大赛算法特训(软件)系列课程】第一课【实用性原则】中涉及到的课上例题的代码实现,加入赛前特训获取全部课程内容请联系【小蓝】。


【课程中涉及的源代码】
1. 猜年龄
【问题描述】
美国数学家维纳(N.Wiener)智力早熟,11岁就上了大学。
他曾在1935~1936年应邀来中国清华大学讲学。
一次,他参加某个重要会议,年轻的脸孔引人注目。
于是有人询问他的年龄,他回答说:
“我年龄的立方是个4位数。我年龄的4次方是个6位数。这10个数字正好包含了从0到9这10个数字,每个都恰好出现1次。”
请你推算一下,他当时到底有多年轻。
【源代码】
【JAVA:于航】

1
2
3
4
5
6
7
8
9
10
11
public class A
    public static void main(String[] args)
        for(int i=1; i<100; i++)
            int a = i * i * i;
            int b = a * i;
            if((a+"").length()!=4continue;
            if((b+"").length()!=6continue;            
            System.out.println(i " = " + a " " + 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
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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#include
#include 

//判断数组里面每一个元素是否相同,相同返回1,不同返回0
int ifDiffInArr(char* arr,int num)

    for (int x 0; x < num-1; x++)
    
        for (int y = x 1; y < num; y++)
        
            if (arr[x== arr[y])
            
                return 1;
            
        
    
    return 0;

//判断数组1和数组2里面每一个元素是否相同,相同返回1,不同返回0
int ifDiffOfArr(char* arr1int num1,char*arr2,int num2)

    for (int x 0; x < num1; x++)
    
        for (int y 0; y < num2; y++)
        
            if (arr1[x== arr2[y])
            
                return 1;
            
        
    
    return 0;


void main()

    char arr1[4 ;//保存立方结果4位数的数组
    char arr2[6 ;//保存4次方结果6位数的数组
    int a, b;//保存立方和4次方的变量
    for (int i 1; i &lt100; i++)//年龄从1到100
    
        //立方过程
        a= i * i * i;
        //把整形转变为数组类型char*
        itoa(a, arr110);
        //判断arr1数组里面的数字是否重复,重复的话就舍掉i,继续判断下一个i++
        if (ifDiffInArr(arr14== 1)
        
            continue;
        

        //4次方过程
        b = a * i;
        //把整形转变为数组类型char*
        itoa(b, arr210);
        //判断arr2数组里面的数字是否重复,重复的话就舍掉i,继续判断下一个i++
        if (ifDiffInArr(arr26== 1)
        
            continue;
        

        //判断数组arr1和arr2里面的数字是否重复,重复的话就舍掉i,继续判断下一个i++;不重复的话就是我们要找的年龄,并打印出来。
        if (ifDiffOfArr(arr1,4,arr2,6)==1)
        
            continue;
         
        else
        
            printf("计算结果如下:\n\n");
            printf("数学家维纳的年龄是:%d\n\n", i);
            printf("年龄的立方是%d,  \n年龄的4次方是:%d。", a, b);
        

    
    

2. 罗马数字
【问题描述】
古罗马帝国开创了辉煌的人类文明,但他们的数字表示法的确有些繁琐,尤其在表示大数的时候,现在看起来简直不能忍受,所以在现代很少使用了。
之所以这样,不是因为发明表示法的人的智力的问题,而是因为一个宗教的原因,当时的宗教禁止在数字中出现0的概念!
罗马数字的表示主要依赖以下几个基本符号:

I –> 1
V –> 5
X –> 10
L –> 50
C –> 100
D –> 500
M –> 1000

这里,我们只介绍一下1000以内的数字的表示法。
单个符号重复多少次,就表示多少倍。最多重复3次。
比如:CCC表示300 XX表示20,但150并不用LLL表示,这个规则仅适用于I X C M。

如果相邻级别的大单位在右,小单位在左,表示大单位中扣除小单位。
比如:IX表示9 IV表示4 XL表示40 
49 = XLIX

更多的示例参见下表,你找到规律了吗? 
I = 1 
II = 2
III = 3
IV = 4
V = 5
VI = 6
VII = 7
VIII = 8
IX = 9 
X = 10
XI = 11
XII = 12
XIII = 13
XIV = 14
XV = 15
XVI = 16
XVII = 17
XVIII = 18
XIX = 19
XX = 20
XXI = 21
XXII = 22
XXIX = 29
XXX = 30
XXXIV = 34
XXXV = 35
XXXIX = 39
XL = 40
L = 50
LI = 51
LV = 55
LX = 60
LXV = 65
LXXX = 80
XC = 90
XCIII = 93
XCV = 95
XCVIII = 98
XCIX = 99
C = 100
CC = 200
CCC = 300
CD = 400
D = 500
DC = 600
DCC = 700
DCCC = 800
CM = 900
CMXCIX = 999

本题目的要求是:请编写程序,由用户输入若干个罗马数字串,程序输出对应的十进制表示。

输入格式是:第一行是整数n,表示接下来有n个罗马数字(n<100)。
以后每行一个罗马数字。罗马数字大小不超过999。
要求程序输出n行,就是罗马数字对应的十进制数据。

例如,用户输入:
3
LXXX
XCIII
DCCII

则程序应该输出:
80
93
702
【源代码】
【JAVA:于航】

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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
//罗马数字的枚举解法
public class A
    
    public static int romeNum(String s)
        int sum 0;
        for(int i=0; i&lt;s.length(); i++) char c = s.charAt(i)if(c==‘I‘) sum += 1if(c==‘V‘) sum += 5if(c==‘X‘) sum += 10if(c==‘L‘) sum += 50if(c==‘C‘) sum += 100if(c==‘D‘) sum += 500if(c==‘M‘) sum += 1000 // 补偿 if(s.indexOf("IV")&gt;=0) sum -= 2;
        if(s.indexOf("IX")&gt;=0) sum -= 2;
        if(s.indexOf("XL")&gt;=0) sum -= 20;
        if(s.indexOf("XC")&gt;=0) sum -= 20;
        if(s.indexOf("CD")&gt;=0) sum -= 200;
        if(s.indexOf("CM")&gt;=0) sum -= 200;
        
        return sum;
    
    
    public static void main(String[] args)
        System.out.println(romeNum("MCCCXIV"));
        System.out.println(romeNum("CMXCIX"));
    

//罗马数字的逆向解法
public class NiXiang

    static String NumRoman(int x)
        int a = x 1000;  // 千位
        int b = x 1000 100;  //百位
        int c = x 100 10;  // 十位
        int d = x 10;
        
        String s "";
        
        if(a==1) s += "M";
        if(a==2) s += "MM";
        if(a==3) s += "MMM";
        
        if(b==1) s += "C";
        if(b==2) s += "CC";
        if(b==3) s += "CCC";
        if(b==4) s += "CD";
        if(b==5) s += "D";
        if(b==6) s += "DC";
        if(b==7) s += "DCC";
        if(b==8) s += "DCCC";
        if(b==9) s += "CM";
        
        if(c==1) s += "X";
        if(c==2) s += "XX";
        if(c==3) s += "XXX";
        if(c==4) s += "XL";
        if(c==5) s += "L";
        if(c==6) s += "LX";
        if(c==7) s += "LXX";
        if(c==8) s += "LXXX";
        if(c==9) s += "XC";
                
        if(d==1) s += "I";
        if(d==2) s += "II";
        if(d==3) s += "III";
        if(d==4) s += "IV";
        if(d==5) s += "V";
        if(d==6) s += "VI";
        if(d==7) s += "VII";
        if(d==8) s += "VIII";
        if(d==9) s += "IX";
        
        return s;   
    
     
    static boolean RomanNumOK(String s)
        for(int i=0; i&lt;4000; i++)
            if(s.equals(NumRoman(i))return true;        
        
return false;    
        

public static void main(String[] args)        
System.out.println(RomanNumOK("CCXLIX"));         
System.out.println(RomanNumOK("CCXXLIX"));        
//System.out.println(NumRoman(3009));    

【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
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
#include 
#include 
#include 
// 罗马数字的枚举解法
int romeNum(char* s,int num)

        int sum 0;
        for (int i 0; i &lt; num; i++)
        
            char c = s[i];
            if (c == ‘I‘
                sum += 1;
            if (c == ‘V‘
                sum += 5;
            if (c == ‘X‘
                sum += 10;
            if (c == ‘L‘
                sum += 50;
            if (c == ‘C‘
                sum += 100;
            if (c == ‘D‘
                sum += 500;
            if (c == ‘M‘
                sum += 1000;
        

        // 补偿
        if (strstr(s,"IV"!= NULL
            sum -= 2;
        if (strstr(s"IX"!= NULL)
            sum -= 2;
        if (strstr(s"XL"!= NULL)
            sum -= 20;
        if (strstr(s"XC"!= NULL)
            sum -= 20;
        if (strstr(s"CD"!= NULL)
            sum -= 200;
        if (strstr(s"CM"!= NULL)
            sum -= 200;

        return sum;


void main()

    

        printf("%d\n",romeNum("MCCCXIV",7));
        printf("%d\n", romeNum("CMXCIX"6));

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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#define _CRT_SECURE_NO_WARNINGS
#include 
#include 
#include 
char s[10];

char* NumRoman(int x)

    int a = x 1000;  // 
    int b = x 1000 100;  //
    int c = x 100 10;  // 
    int d = x 10;

    for (int x 0; x &lt1024;x++)
    
        s[x‘0‘;
    

    if (a == 1)
        strcat(s"M");
    if (a == 2)
        strcat(s"MM");
    if (a == 3)
        strcat(s"MMM");


    if (b == 1)
        strcat(s"C");
    if (b == 2)
        strcat(s"CC");
    if (b == 3)
        strcat(s"CCC");
    if (b == 4)
        strcat(s"CD");
    if (b == 5)
        strcat(s"D");
    if (b == 6)
        strcat(s"DC");
    if (b == 7)
        strcat(s"DCC");
    if (b == 8)
        strcat(s"DCCC");
    if (b == 9)
        strcat(s"CM");

    if (c == 1)
        strcat(s"X");
    if (c == 2)
        strcat(s"XX");
    if (c == 3)
        strcat(s"XXX");
    if (c == 4)
        strcat(s"XL");
    if (c == 5)
        strcat(s"L");
    if (c == 6);
    strcat(s"LX");
    if (c == 7)
        strcat(s"LXX");
    if (c == 8)
        strcat(s"LXXX");
    if (c == 9)
        strcat(s"XC");

    if (d == 1)
        strcat(s"I");
    if (d == 2)
        strcat(s"II");
    if (d == 3)
        strcat(s"III");
    if (d == 4)
        strcat(s"IV");
    if (d == 5)
        strcat(s"V");
    if (d == 6)
        strcat(s"VI");
    if (d == 7)
        strcat(s"VII");
    if (d == 8)
        strcat(s"VIII");
    if (d == 9)
        strcat(s"IX");

    return s;


int  RomanNumOK(char * s)

    for (int i 0; i &lt4000; i++)
    
        char *p = NumRoman(i);
        int x strcmp(p, s);
        /*free(p);*/
        if (!x)
            return 1;
    
    return 0;


void main()


    int num1 = RomanNumOK("CCXLIX");
    int num2 = RomanNumOK("CCXXLIX");
    //System.out.println(NumRoman(3009));

3. 九宫幻方
【问题描述】

小明最近在教邻居家的小朋友小学奥数,而最近正好讲述到了三阶幻方这个部分。
三阶幻方指的是将1~9不重复的填入一个3*3的矩阵当中,使得每一行、每一列和每一条对角线的和都是相同的。
三阶幻方又被称作九宫格,在小学奥数里有一句非常有名的口诀:
“二四为肩,六八为足,左三右七,戴九履一,五居其中”,
通过这样的一句口诀就能够非常完美的构造出一个九宫格来。
4 9 2
3 5 7
8 1 6
有意思的是,所有的三阶幻方,都可以通过这样一个九宫格进行若干镜像和旋转操作之后得到。
现在小明准备将一个三阶幻方(不一定是上图中的那个)中的一些数抹掉,交给邻居家的小朋友来进行还原,并且希望她能够判断出究竟是不是只有一个解。

而你呢,也被小明交付了同样的任务,但是不同的是,你需要写一个程序~

输入格式:
输入仅包含单组测试数据。
每组测试数据为一个3*3的矩阵,其中为0的部分表示被小明抹去的部分。
对于100%的数据,满足给出的矩阵至少能还原出一组可行的三阶幻方。

输出格式:
如果仅能还原出一组可行的三阶幻方,则将其输出,否则输出“Too Many”(不包含引号)。

样例输入
0 7 2
0 5 0
0 3 0

样例输出
6 7 2
1 5 9
8 3 4
【源代码】
【JAVA:于航】

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
/*
4 9 2
3 5 7
8 1 6
"492357816"

8 3 4
1 5 9
6 7 2
"834159672"

0 7 2
0 5 0
0 3 0

*/
public class A

    static boolean test(String std, String s)
        for(int i=0; i&lt;std.length(); i++)
            if(std.charAt(i== s.charAt(i)continue;
            if(s.charAt(i)==‘0‘continue;
            return false;
        
        
        return true;
    
    
    public static void main(String[] args)
        
        String s "072050030";
        
        String[] ss 
            "492357816",
            "834159672",
            "618753294",
            "276951438",
            "294753618",
            "438951276",
            "816357492",
            "672159834"
        ;
        
        for(int i=0; i&lt;ss.length; i++)
            if(test(ss[i],s))
                System.out.println(ss[i].substring(0,3));
                System.out.println(ss[i].substring(3,6));
                System.out.println(ss[i].substring(6,9));               
            
        
    

【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
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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include 
#include 

int test(char* stdint num1char* sint num2)

    for (int i 0; i &lt; num1; i++)
    
        if (std[i== s[i])
            continue;
        if (s[i== ‘0‘
            continue;
        return 0;
    
    return 1;


char * myItoa(int num)

    char * p malloc(1024 1);
    itoa(num,p10);
    return p;


void main3()

    char* arr1 = myItoa(172050030);
    arr1[0‘0‘;

    char *  p0 = myItoa(492357816);
    char *  p1 = myItoa(834159672);
    char *  p2 = myItoa(618753294);
    char *  p3 = myItoa(276951438);
    char *  p4 = myItoa(294753618);
    char *  p5 = myItoa(438951276);
    char *  p6 = myItoa(816357492);
    char *  p7 = myItoa(672159834);
    char *  pp[8 p0, p1, p2, p3, p4, p5, p6, p7 ;


    for (int i 0; i &lt8; i++)
    
        if (test(pp[i]7, arr1,7))
        
            for (int x 0; x &lt3;x++)
            
                printf("%c ", pp[i][x]);
            
            printf("\n");
            for (int x 3; x &lt6; x++)
            
                printf("%c ", pp[i][x]);
            
            printf("\n");
            for (int x 6; x &lt9; x++)
            
                printf("%c ", pp[i][x]);
            
            printf("\n");

        
    
    for (int i 0; i &lt8; i++)
    
        if (pp[i!= NULL)
        
            free(pp[i]);
        
    

4. 魔方旋转
【问题描述】
魔方可以对它的6个面自由旋转。

我们来操作一个2阶魔方(如图1所示):
为了描述方便,我们为它建立了坐标系。

各个面的初始状态如下:
x轴正向:绿
x轴反向:蓝
y轴正向:红
y轴反向:橙
z轴正向:白
z轴反向:黄

假设我们规定,只能对该魔方进行3种操作。分别标记为:
x 表示在x轴正向做顺时针旋转
y 表示在y轴正向做顺时针旋转
z 表示在z轴正向做顺时针旋转

xyz 则表示顺序执行x,y,z 3个操作

题目的要求是:
用户从键盘输入一个串,表示操作序列。
程序输出:距离我们最近的那个小方块的3个面的颜色。
顺序是:x面,y面,z面。

例如:在初始状态,应该输出:
绿红白

初始状态下,如果用户输入:
x
则应该输出:
绿白橙

初始状态下,如果用户输入:
zyx
则应该输出:
红白绿
技术分享图片

面的标号
技术分享图片

模仿旋转示意图

【源代码】
【JAVA:于航】

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
54
55
56
57
58
59
60
61
62
63
/*
  二阶魔方的各个面给一个唯一编号:
  
         16 17
         19 18
        ------- 
 12 13 |  0  1 |  4  5 |  8  9
 15 14 |  3  2 |  7  6 | 11 10
        -------
         20 21
         23 22
         
         上
       左前右后
         下
         
x操作:(0,1,2,3)  (4,21,14,19)  (7,20,13,18)
y操作:(4,5,6,7)  (1,17,11,21)  (2,18,8,22)
z操作:(16,17,18,19) (0,12,8,4)  (1,13,9,5)         
*/

public class A

    static int[][] transx=0,1,2,3,4,21,14,19,7,20,13,18;
    static int[][] transy=4,5,6,7,1,17,11,21,2,18,8,22;
    static int[][] transz=16,17,18,19,0,12,8,4,1,13,9,5;
    
    static char[] op(char[] a,int[][] trans)
        char[] b = java.util.Arrays.copyOf(a,a.length);
        
        for(int i=0; i&lt;trans.length; i++)
            b[trans[i][1]= a[trans[i][0]];
            b[trans[i][2]= a[trans[i][1]];
            b[trans[i][3]= a[trans[i][2]];
            b[trans[i][0]= a[trans[i][3]];
        
        return b;
    
    
    static char[] op(char[] a, String s)
        char[] b = java.util.Arrays.copyOf(a, a.length);
        for(int i=0; i&lt;s.length(); i++)
            if(s.charAt(i)==‘x‘) b = op(b, transx);
            if(s.charAt(i)==‘y‘) b = op(b, transy);
            if(s.charAt(i)==‘z‘) b = op(b, transz);
        
        return b;
    
    
    public static void main(String[] args)
        char[] init =  ‘绿‘,‘绿‘,‘绿‘,‘绿‘,
                        ‘红‘,‘红‘,‘红‘,‘红‘,
                        ‘蓝‘,‘蓝‘,‘蓝‘,‘蓝‘,
                        ‘橙‘,‘橙‘,‘橙‘,‘橙‘,
                        ‘白‘,‘白‘,‘白‘,‘白‘,
                        ‘黄‘,‘黄‘,‘黄‘,‘黄‘,;
                        
        //char[] b = op(init, "xyxyzzxyxyzz");
        char[] b = op(init, "x");
        System.out.println(""+b[1]+b[4]+b[18]);
        
    

【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
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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#include 
#include 
#include 

int transx[4][4  012 4211419  7201318  ;
int transy[4][4  456 1171121  218822  ;
int transz[4][4  16171819  0128 1139 ;

char * op(char *p,int num1,int pp[4][4],int num2)

    char * arrb malloc(num1*sizeof(char));
    strncpy(arrb, p, num1);

    for (int i 0; i &lt; num2; i++)
    
        arrb[pp[i][1]= p[pp[i][0]];
        arrb[pp[i][2]= p[pp[i][1]];
        arrb[pp[i][3]= p[pp[i][2]];
        arrb[pp[i][0]= p[pp[i][3]];
    
    return arrb;

void printfCh(char a)

    switch (a)
    
    case ‘0‘:
        printf("绿");
        break;
    case ‘1‘:
        printf("红");
        break;
    case ‘2‘:
        printf("蓝");
        break;
    case ‘3‘:
        printf("橙");
        break;
    case ‘4‘:
        printf("白");
        break;
    case ‘5‘:
        printf("黄");
        break;
    default:
        break;
    



char * op1(char *aint num1char *s,int num2)

    char * arrb malloc(num1*sizeof(char));
    strncpy(arrb, a, num1);

    for (int i 0; i &lt; num2; i++)
    
        if (s[i== ‘x‘
            arrb = op(arrb, num1, transx3);
        if (s[i== ‘y‘
            arrb = op(arrb, num1, transy3);
        if (s[i== ‘z‘
            arrb = op(arrb, num1, transz3);
    
    return arrb;


void main()
    char init[ ‘0‘‘0‘‘0‘‘0‘,
        ‘1‘‘1‘‘1‘‘1‘,
        ‘2‘‘2‘‘2‘‘2‘,
        ‘3‘‘3‘‘3‘‘3‘,
        ‘4‘‘4‘‘4‘‘4‘,
        ‘5‘‘5‘‘5‘‘5‘;
    
        //char[] b = op(init, "xyxyzzxyxyzz");
        char* b = op1(init24"x"1);
        printfCh(b[1]);
        printfCh(b[4]);
        printfCh(b[18]);
;

    

【课后作业】
【信用卡号的验证】

当你输入信用卡号码的时候,有没有担心输错了而造成损失呢?其实可以不必这么担心,因为并不是一个随便的信用卡号码都是合法的,它必须通过Luhn算法来验证通过。
该校验的过程:
1、从卡号最后一位数字开始,逆向将奇数位(1、3、5等等)相加。
2、从卡号最后一位数字开始,逆向将偶数位数字,先乘以2(如果乘积为两位数,则将其减去9),再求和。
3、将奇数位总和加上偶数位总和,结果应该可以被10整除。
例如,卡号是:5432123456788881

则,奇数位和=35
偶数位乘以2(有些要减去9)的结果:1 6 2 6 1 5 7 7,求和=35。
最后35+35=70 可以被10整除,认定校验通过。

请编写一个程序,从键盘输入卡号,然后判断是否校验通过。通过显示:“成功”,否则显示“失败”。
比如,用户输入:356827027232780
程序输出:成功

【参考测试用例】
356406010024817 成功
358973017867744 成功
356827027232781 失败
306406010024817 失败
358973017867754 失败

【代码示例】

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
public class A

    // s: 待验证的卡号
    static boolean f(String s)
        int sum 0;
        for(int i=0; i&lt;s.length(); i++) int x = s.charAt(s.length()-i-1)-‘0‘if(i%2==1) x = x 2if(x&gt;=10) x -= 9;
            
            sum += x;
        
        return sum 10 == 0;
    
    
    public static void main(String[] args)
        System.out.println(f("356827027232780"));
        System.out.println(f("356406010024817"));
        System.out.println(f("358973017867744"));
        System.out.println(f("356827027232781"));
        System.out.println(f("306406010024817"));
        System.out.println(f("358973017867754"));       
    


public class B

    // s: 待验证的卡号
    static boolean f(String s)
        int[] EV 0,2,4,6,8,1,3,5,7,9;
        int sum 0;
        for(int i=0; i&lt;s.length(); i++)
            int x = s.charAt(s.length()-i-1)-‘0‘;
            if(i%2==1) x = EV[x];
            sum += x;
        
        return sum 10 == 0;
    
    
    public static void main(String[] args)
        System.out.println(f("356827027232780"));
        System.out.println(f("356406010024817"));
        System.out.println(f("358973017867744"));
        System.out.println(f("356827027232781"));
        System.out.println(f("306406010024817"));
        System.out.println(f("358973017867754"));       
    

如果您需要更多课程内容和讲解视频,请联系小蓝

 

 

蓝桥杯算法特训第二课【递归原理与构造技巧】源代码

技术分享图片

【内容简介】
本文章内容为【2018蓝桥杯大赛算法特训(软件)系列课程】第二课【递归原理与构造技巧】中涉及到的课上例题的代码实现,加入赛前算法特训获取全部课程内容请联系【小蓝】。


【课程中涉及的源代码】
1. 串的翻转
【问题描述】
【源代码】
【JAVA:于航】

 

1
2
3
4
5
6
7
8
9
10
11
public class A

    static String f(String s)
        if(s.length()&lt;=1return s;
        return f(s.substring(1)+ s.charAt(0);
    
    
    public static void main(String[] args)
        System.out.println(f("abcde"));
    

【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
25
26
27
28
29
30
31
#define _CRT_SECURE_NO_WARNINGS
#include 
#include 
#include 

char * f(char * sint num)

    if (num &lt;= 1)
    
        return s;
    
    else
    
        char *p (char *)malloc(num+1);
        memset(p0, num+1);
        strcpy(p, s+1);
        char *pp = f(p, num-1);         
        strcpy(p, pp);
        if (p!=pp)
            free(pp);
        strncpy(p+num-1,s,1);       
        return p;
    


void main()

    char arr[100"abcde";
    printf("%s", f(arr5));

 


2. 循环改递归
【问题描述】
【源代码】
【JAVA:于航】

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class A

    static void f(int a, int b)
        for(int i=a; i&lt;=b; i++)
            System.out.println(i);
        
    
    
    static void g(int a, int b)
        if(a&lt;b) g(a,b-1);
        System.out.println(b);
    
    
    public static void main(String[] args)
        //f(1,10);  
        g(1,10);
    

【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 
#include 
#include 

void f2(int aint b)

    for (int i = a; i &lt;= b; i++)
        printf("%d ",i);
    


void g2(int aint b)

    if (a &lt; b
        g2(a, b 1);
    printf("%d   ",b);


void main()

    //f2(1,10); 
    g2(110);

 


3. 出栈次序
【问题描述】
X星球特别讲究秩序,所有道路都是单行线。
一个甲壳虫车队,共16辆车,按照编号先后发车,夹在其它车流中,缓缓前行。
路边有个死胡同,只能容一辆车通过,是临时的检查站,如图所示。
技术分享图片
X星球太死板,要求每辆路过的车必须进入检查站,也可能不检查就放行,也可能仔细检查。
如果车辆进入检查站和离开的次序可以任意交错。那么,该车队再次上路后,可能的次序有多少种?
为了方便起见,假设检查站可容纳任意数量的汽车。
显然,如果车队只有1辆车,可能次序1种;2辆车可能次序2种;3辆车可能次序5种。
【源代码】
【JAVA:于航】

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
/*
  如果进栈次序为:1 2 3 4 5 。。。
  出栈次序有多少种情况?
  
*/

public class A

    // n 个等着进栈,栈中有m个
    static int f(int n, int m)
    
        if(n==0return 1;
        if(m==0return f(n-1,1);
        return f(n,m-1+ f(n-1, m+1);
    
    
    static int f(int n)
    
        return f(n, 0);
    
    
    public static void main(String[] args)
    
        for(int i=1; i&lt;17; i++)
            System.out.println(i ": " + f(i));
        
    

【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
25
26
27
28
29
30
31
32
#define _CRT_SECURE_NO_WARNINGS
#include 
#include 
/*
如果进栈次序为:1 2 3 4 5 。。。
出栈次序有多少种情况?

*/

    // n 个等着进栈,栈中有m个
    int f3(int nint m)
    
        if (n == 0
            return 1;
        if (m == 0
            return f3(n 11);
        return 
            f3(n, m 1+ f3(n 1, m 1);
    

    int f5(int n)
    
        return f3(n0);
    

    void main()
    
        for (int i 1; i&lt;17; i++)
        
            printf("%d : %d \n", i, f5(i));
        
    

 


4. 第39级台阶
【问题描述】

小明刚刚看完电影《第39级台阶》。离开电影院的时候,他数了数礼堂前的台阶数,恰好是39级!
站在台阶前,他突然又想着一个问题:
如果我每一步只能迈上1个或2个台阶。先迈左脚,然后左右交替,最后一步是迈右脚,也就是说一共要走偶数步。那么,上完39级台阶,有多少种不同的上法呢?
请你利用计算机的优势,帮助小明寻找答案。

【源代码】
【JAVA:于航】

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
public class A

    // 奇数步
    static long g(int n)
    
        if(n==0return 0;
        if(n==1return 1;
        //if(n==2) return 1;
        
        return f(n-1+ f(n-2);
    
    
    // 偶数步
    static long f(int n)
    
        if(n==0return 1;
        if(n==1return 0;
        //if(n==2) return 1;
        
        return g(n-1+ g(n-2);
    
    
    public static void main(String[] args)
    
        System.out.println(f(5));
        System.out.println(f(39));
    

【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
25
26
27
28
29
30
31
32
33
34
35
#define _CRT_SECURE_NO_WARNINGS
#include 
#include 
#include 

long ff(int n);
    // 奇数步
long gg(int n)

    if (n == 0
        return 0;
    if (n == 1
        return 1;
    /*if(n==2)
        return 1;*/
    return ff(n 1+ ff(n 2);


    // 偶数步
long ff(int n)

    if (n == 0
        return 1;
    if (n == 1
        return 0;
    /*if(n==2)
        return 1;*/
    return gg(n 1+ gg(n 2);


void main()

        printf("%d \n",ff(5));
        printf("%d ", ff(39));

5. 算式填符号
【问题描述】

匪警请拨110,即使手机欠费也可拨通!
为了保障社会秩序,保护人民群众生命财产安全,警察叔叔需要与罪犯斗智斗勇,因而需要经常性地进行体力训练和智力训练!

某批警察叔叔正在进行智力训练:
1 2 3 4 5 6 7 8 9 = 110

请看上边的算式,为了使等式成立,需要在数字间填入加号或者减号(可以不填,但不能填入其它符号)。之间没有填入符号的数字组合成一个数,例如:12+34+56+7-8+9 就是一种合格的填法;123+4+5+67-89 是另一个可能的答案。

请你利用计算机的优势,帮助警察叔叔快速找到所有答案。
每个答案占一行。形如:
12+34+56+7-8+9
123+4+5+67-89
……

【源代码】
【JAVA:于航】

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
public class SuanShi

    //a: 参加计算的元素
    //k: 目前考虑的元素下标
    //so: 合成好的结果串
    //goal: 计算目标
    static void f(int[] a, int k, String so, int goal)
        if(k==0)
            if(a[0== goal)
                System.out.println(a[0]+so);
            
            return;
        
        
        f(a,k-1,"+"+a[k]+so, goal-a[k]);
        f(a,k-1,"-"+a[k]+so, goal+a[k]);
        int old = a[k-1];
        a[k-1Integer.parseInt("" + a[k-1+ a[k]);
        f(a,k-1,so,goal);
        a[k-1= old;
    
    
    public static void main(String[] args)
        int[] a 1,2,3,4,5,6,7,8,9;      
        f(a,8,"",110);
    

【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
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
#define _CRT_SECURE_NO_WARNINGS
#include 
#include 
#include 

    //a: 参加计算的元素
    //k: 目前考虑的元素下标
    //so: 合成好的结果串
    //goal: char
    void fk(int *aint kchar *sint goal)
        if (k == 0)
            if (a[0== goal)
                printf("%d%s\n",a[0],s);
            
            return;
        

        char * p malloc(k 1);
        memset(p0, k 1);

        p[0‘+‘;
        _itoa(a[k], p+110);
        int x strlen(p);
        strcat(p+x, s);     
        fk(a, k 1, p, goal - a[k]);

        p[0‘-‘;
        fk(a, k 1, p, goal + a[k]);


        int old = a[k 1];
        char ak[1024 ;
        char ak2[1024 ;
        _itoa(a[k 1], ak10);
        _itoa(a[k], ak210);
        strcat(ak, ak2);
        a[k 1atoi(ak);
        memset(p0, k 1);
        strcat(p, s);
        fk(a, k 1, p, goal);
        a[k 1= old;
    


    
    void main()
    
        int a[ 12345678;
        fk(a8""110);
    

 


6. 找钱问题
【问题描述】

公园票价为5角。假设每位游客只持有两种币值的货币:5角、1元。
再假设持有5角的有m人,持有1元的有n人。
由于特殊情况,开始的时候,售票员没有零钱可找。
我们想知道这m+n名游客以什么样的顺序购票则可以顺利完成购票过程。
显然,m < n的时候,无论如何都不能完成;
m>=n的时候,有些情况也不行。比如,第一个购票的乘客就持有1元。
请计算出这m+n名游客所有可能顺利完成购票的不同情况的组合数目。
注意:只关心5角和1元交替出现的次序的不同排列,持有同样币值的两名游客交换位置并不算做一种新的情况来计数。

【源代码】
【JAVA:于航】

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
//考虑最后一个人
public class ZhaoQian1

    //m: 持有5角的
    //n: 持有1元的
    static int f(int m, int n)
        if(m&lt;nreturn 0;
        if(m==1return 1;
        if(n==0return 1;
            
        return f(m-1,n+ f(m,n-1);
    
    
    public static void main(String[] args)
        System.out.println(f(2,2));
        System.out.println(f(3,2));
        System.out.println(f(5,3));
    


//考虑第一个人
public class ZhaoQian2

    //m: 持有5角的
    //n: 持有1元的
    //t: 售票员手里有多少个5角的
    static int f(int m, int n, int t)
        if(m+t&lt;nreturn 0if(m==0return 1if(n==0return 1int r = f(m-1,n,t+1)if(t&gt;0) r += f(m,n-1,t-1)
        return r;
    
    
    public static void main(String[] args)
        System.out.println(f(2,2,0));
        System.out.println(f(3,2,0));
        System.out.println(f(5,3,0));
    

【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
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
#define _CRT_SECURE_NO_WARNINGS
#include 
#include 
#include 
//考虑最后一个人
//m: 持有5角的
//n: 持有1元的
int f6(int mint n)

    if (m &lt; n
        return 0;
    if (m == 1
        return 1;
    if (n == 0
        return 1;

    return f6(m 1, n+ f6(m, n 1);


void main()
    printf("%d \n",f6(22));
    printf("%d \n",f6(32));
    printf("%d \n",f6(53));



//==========================================

#define _CRT_SECURE_NO_WARNINGS
#include 
#include 
#include 
//考虑第一个人
//m: 持有5角的
//n: 持有1元的
//t: 售票员手里有多少个5角的
int fn(int mint nint t)

    if (m + t&lt;nreturn 0if (m == 0return 1if (n == 0return 1int r = fn(m 1, n, t 1)if (t&gt;0
        r += fn(m, n 1, t 1);
    return r;


void main()

    printf("%d \n", fn(220));
    printf("%d \n", fn(320));
    printf("%d \n", fn(530));


7. 振兴中华
【问题描述】
小明参加了学校的趣味运动会,其中的一个项目是:跳格子。
地上画着一些格子,每个格子里写一个字,如下所示:(也可参见下图)

从我做起振
我做起振兴
做起振兴中
起振兴中华
技术分享图片
比赛时,先站在左上角的写着“从”字的格子里,可以横向或纵向跳到相邻的格子里,但不能跳到对角的格子或其它位置。一直要跳到“华”字结束。

要求跳过的路线刚好构成“从我做起振兴中华”这句话。
请你帮助小明算一算他一共有多少种可能的跳跃路线呢?

【源代码】
【JAVA:于航】

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class A

    static int f(int m, int n)
    
        if(m==|| n==1return 1;
        
        return f(m-1,n+ f(m,n-1);
    
    
    public static void main(String[] args)
    
        System.out.println(f(5,4));
        //System.out.println(f(3,2));
    

【C语言:志愿者】

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#define _CRT_SECURE_NO_WARNINGS
#include 
#include 
#include 
int f7(int mint n)

    if (m == || n == 1
        return 1;
    return f7(m 1, n+ f7(m, n 1);


void main7()

    printf("%d \n", f7(54));
    //printf("%d \n", f7(3, 2));

























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































沈逸老师php魔鬼特训笔记--进化

回到第一课,我们学过PHP母体,了解过解析PHP程序。PHP其实内置了一个web服务器,专门给我们开发测试使用,那么接下来我们要完成的是:生成后创建一个web服务,在浏览器中可以访问。  PHP的母体,还能加入参数后启动一些... 查看详情

沈逸老师php魔鬼特训笔记

一、这一课会学习到几个懒人函数:1、file_put_contents    (PHP5,PHP7)    file_put_contents—将一个字符串写入文件  说明    intfile_put_contents(string$filename,mixed$data[,int$flags=0[,resource$context]])    和依次调用fopen(),... 查看详情

text第一课(代码片段)

查看详情

《开学第一课》观后感—吕中琪

    伴随着《开学第一课》的开场曲,我观看了2018年以“创造向未来”为主题的《开学第一课》。    开学第一课,一共有四堂课。    第一堂课是以“梦想”为主题,主讲人是被誉为... 查看详情

第一课

markdown学习 标题三级标题###四级标题二级标题三级标题Hello,World!Hello,world!引用努力学习分割线 图片[跳转到B站狂神视频超链接狂神视频列表 代码···Java1.publc       查看详情

vba学习第一课

Subgzt()DimiAsIntegerFori=1To10Selection.CopyActiveCell.Offset(2,0).Rows("1:1").EntireRow.SelectSelection.InsertShift:=xlDownNextEndSub  查看详情

phtyon第一课

1.网络编程是应用程序的第一步,也就是一个程序大厦的地基。2.程序语言的语句语法结构相当于程序的砖和瓦。3.web框架则是程序大厦的梁和柱。4.设计和算法等于建造程序大厦的想法和技巧。  查看详情

beautifulsoup第一课

fromurllib.requestimporturlopenfromurllib.errorimportHTTPErrorfrombs4importBeautifulSoupdefgetTitle(url):    try:        html=urlopen(url)&n 查看详情

bashshell第一课

    自学shell,又被老师说教,上英语课不好好学习英语四级怎么过,哈哈,那也没有数据对我的吸引力大啊,为了爱与梦想!!!     回忆一下文件格式: 文件名的扩展名为.sh              ... 查看详情

html第一课

<标签名属性>内容</标签名><标签/>静态网页与动态网页的区别:是否从数据库提取数据相对路径跟绝对路径../代表高一级的&nbsp牛逼的空格<fontface="微软雅黑"color="#000000"size="7">变换字体</font><strong>加... 查看详情

前端第一课

+++++++++++++++++++代码区++++++++++++++++++++++++++<!DOCTYPEhtml><htmllang="en"><head> <metacharset="UTF-8"> <title>Document</title></head><body><p>常 查看详情

第三章第一课外观和声音

切换造型创建动画 查看详情

第一课:超级helloarduino.使用多种知识串联一个入门小项目,很适合初学第一课哟.(代码片段)

开关+led+旋钮电位器的实验视频已经购买Arduino开发版的同学,开始上课~来一场紧张刺激的helloArduino之旅吧~前言开发工具的下载,安装,使用都很简单,我这里就不赘述了,附上官方的说明,跟着步骤来,十分钟搞定~相关连接ide下载... 查看详情

javaweb第一课

了解javawebJavaWeb应用由一组Servlet、HTML页、类、以及其他可以被绑定的资源构成。它可以在各种供应商提供的实现Servlet规范的Servlet容器中运行。JavaWeb包含如下内容:ServletJsp实用类静态文档如HTML、图片等描述Web应用的信息(web.xm... 查看详情

css第一课

学习内容:1.CSS的引入方式:(1)内联样式表直接在标签内引用,引入方式<标签名style="样式1:值;样式2:值">,样式之间用分号分隔1<pstyle="color:red;font-szie:12px;">这是红色,12px大小的字</p>(2)内部样式表在head标签中... 查看详情

重学java基础第一课:解决大家的疑问

  查看详情

重学java基础第一课:解决大家的疑问

  查看详情

java学习第一课

2020-01-14 19:57:451.安装JDK2.编写第一个java程序,保存文件名HelloWorld.javapublicclassHelloWorld{ publicstaticvoidmain(String[]args){ System.out.println("HelloWorld"); } }3.运行java javacHelloWorld   4 查看详情