刷算法题

1.模拟

1.xxx定律
提交网址
在这里插入图片描述

#include <cstdio>

int main(){
    int n;
    while(scanf("%d",&n) != EOF){
        int count = 0;
        while(n != 1){
            if(n%2 ==0){//n为偶数
                n = n/2;
            }else{//n为奇数
                n = (3*n+1)/2; 
            }
            count++;
        }    
        printf("%d\n",count);
    }
    return 0;
}

2.学分绩点 (求GPA)
提交网址:https://www.nowcoder.com/practice/a0c09a7e0da04e728810a8aca7226b7b
在这里插入图片描述

#include <cstdio>

float getGradeClass(int grade){
    float gradeclass;
    if( 90<=grade && grade<=100){
        gradeclass = 4.0;
    }else if(85<=grade && grade<=89){
        gradeclass = 3.7;
    }else if(82<=grade && grade<=84){
        gradeclass = 3.3;
    }else if(78<=grade && grade<=81){
        gradeclass = 3.0;
    }else if(75<=grade && grade<=77){
        gradeclass = 2.7;
    }else if(72<=grade && grade<=74){
        gradeclass = 2.3;
    }else if(68<=grade && grade<=71){
        gradeclass = 2.0;
    }else if(64<=grade && grade<=67){
        gradeclass = 1.5;
    }else if(60<=grade && grade<=63){
        gradeclass = 1.0;
    }else{
        gradeclass = 0;
    }
    return gradeclass;
}

int main(){
    int n;
    scanf("%d",&n);
    int credit[10];//学分
    int sum_credit = 0;//总学分
    int grade[10];//单科成绩
    float gradeclass[10];//成绩对应的绩点
    float subjectclass[10];//学科绩点 = 成绩对应绩点*学分
    float sum_subjectclass = 0;//学科绩点之和
    //输入学分
    for(int i = 0; i < n; ++i){
        scanf("%d",&credit[i]);
        sum_credit += credit[i];
    }
    //输入成绩
    for(int i = 0; i < n; ++i){
        scanf("%d",&grade[i]);
        gradeclass[i] = getGradeClass(grade[i]);
        subjectclass[i] = gradeclass[i]*credit[i];
        sum_subjectclass += subjectclass[i];
    }

    float GPA = sum_subjectclass/sum_credit;
    printf("%0.2f",GPA);
    return 0;
}

1.switch case 与 if else 的区别

if else需要从头到尾遍历每个if,但switch会直接找到对应的case。

  • 当分支较多时,switch case效率更高
  • if else更灵活,应用场景更多
    所以,switch case是if else在特定情形下的优化。

学习网址:http://m.biancheng.net/view/171.html
switch的一般形式如下:

switch (表达式)
{
    case 常量表达式1:    语句1
    case 常量表达式2:    语句2case 常量表达式n:    语句n
    default:        语句n+1
}

举例:

# include <stdio.h>
int main(void)
{
    int val;  //variable的缩写, “变量”的意思
    printf("请输入您想去的楼层:");
    scanf("%d", &val);
    switch (val)
    {
        case 1:
            printf("1层开!\n");
            break;
        case 2:
            printf("2层开!\n");
            break;
        case 3:
            printf("3层开!\n");
            break;
        default:
            printf("该层不存在, 请重新输入\n");
    }
    return 0;
}

3.加减乘除
在这里插入图片描述
提交网址:https://www.nowcoder.com/practice/fdc56f9b00b34c70ad36c61ef89e3fc3

解法1:if else

#include <cstdio>

long long int Factorial(int n){
    if(n == 0){
        return 1;
    }else{
        return n*Factorial(n-1);
    }
}

int main(){
    int a,c;
    char b;
    while(scanf("%d %c",&a,&b) != EOF){
        if(b == '+'){
            scanf("%d",&c);
            printf("%d\n",a+c);
        }else if(b == '-'){
            scanf("%d",&c);
            printf("%d\n",a-c);
        }else if(b == '*'){
            scanf("%d",&c);
            printf("%d\n",a*c);
        }else if(b == '!'){
            printf("%lld\n",Factorial(a));
        }else if(b == '/'){
            scanf("%d",&c);
            if(c == 0){
                printf("error\n");
            }else{
                printf("%d\n",a/c);
            }
        }else if(b == '%'){
            scanf("%d",&c);
            if(c == 0){
                printf("error\n");
            }else{
                printf("%d\n",a%c);
            }
        }
    }
    return 0;
}

解法2:switch case

#include <cstdio>

long long int Factorial(int n){
    if(n == 0){
        return 1;
    }else{
        return n*Factorial(n-1);
    }
}

int main(){
    int a,c;
    char b;
    while(scanf("%d %c",&a,&b) != EOF){
        if(b == '!'){
            printf("%lld\n",Factorial(a));
        }else{
            scanf("%d",&c);
            switch(b){
                case '+':
                    printf("%d\n",a+c);
                    break;
                case '-':
                    printf("%d\n",a-c);
                    break;
                case '*':
                    printf("%d\n",a*c);
                    break;
                case '/':
                    if(c == 0){
                        printf("error\n");
                    }else{
                        printf("%d\n",a/c);
                    }
                    break;
                case '%':
                    if(c == 0){
                        printf("error\n");
                    }else{
                        printf("%d\n",a%c);
                    }
                    break;
            }
        }
    }
    return 0;
}

4.统计同成绩学生人数
在这里插入图片描述

提交网址:https://www.nowcoder.com/practice/987123efea5f43709f31ad79a318ca69

#include <cstdio>

int main(){
    int n;
    int arr[1001];
    int target;
    while(scanf("%d",&n) != EOF){
        if(n <= 0){
            //do nothing
        }else{ //n>0
            for(int i = 0; i < n; ++i){
                scanf("%d",&arr[i]);
            }
            scanf("%d",&target);
            int num = 0;
            for(int i = 0; i < n; ++i){
                if(arr[i] == target){
                    num++;
                }
            }
            printf("%d\n",num);
        }
    }
    return 0;
}

5.数字之和
在这里插入图片描述
提交网址:https://www.nowcoder.com/practice/ae759916631f4711a90c4d4d9657f4b0

解法1:非常麻烦地把数字n的每一位保存进数组中

#include <cstdio>
#include <string>
using namespace std;

void sum1(int n){
    string str = to_string(n);
    int arr[400000];
    int len = str.length();
    for(int i = len; i >= 0; --i){
            arr[i-1] = n%10;
            n = n/10;
    }
    int sum1 = 0;
    for(int i = 0; i < len; ++i){
        sum1 += arr[i];
    }
    printf("%d ",sum1);
}

void sum2(int n){
    int sn = n*n;
    string str = to_string(sn);
    int arr[400000];
    int len = str.length();
    for(int i = len; i >= 0; --i){
            arr[i-1] = sn%10;
            sn = sn/10;
    }
    int sum2 = 0;
    for(int i = 0; i < len; ++i){
        sum2 += arr[i];
    }
    printf("%d\n",sum2);
}

int main(){
    int n;
    while(scanf("%d",&n) != EOF){
        sum1(n);
        sum2(n);
    }
    return 0;
}

解法2:直接求每位和,不用保存到数组中

#include <cstdio>

int main(){
    int n;
    while(scanf("%d",&n) != EOF){
        long long int sn = n*n;
        int sum1 = 0,sum2 =0;
        while(n){
            sum1 += n%10; //根本不需要把每一位存入数组中
            n/= 10;
        }
        printf("%d ",sum1);

        while(sn){
            sum2 += sn%10;
            sn /= 10;
        }
        printf("%d\n",sum2);
    }
    return 0;
}

6.计算两个矩阵的乘积
在这里插入图片描述
提交网址:https://www.nowcoder.com/practice/ed6552d03e624ba58d16af6d57e1c3e9

解法1:暴力解

#include <cstdio>

int main(){
    int a11,a12,a13,a21,a22,a23;
    int b11,b12,b21,b22,b31,b32;
    int c11,c12,c21,c22;

    scanf("%d%d%d%d%d%d%d%d%d%d%d%d",
                    &a11,&a12,&a13,&a21,&a22,&a23,
                    &b11,&b12,&b21,&b22,&b31,&b32);
    c11 = a11*b11 + a12*b21 + a13*b31;
    c12 = a11*b12 + a12*b22 + a13*b32;
    c21 = a21*b11 + a22*b21 + a23*b31;
    c22 = a21*b12 + a22*b22 + a23*b32;
    printf("%d %d\n%d %d\n",c11,c12,c21,c22);
    return 0;
}

解法2:二维数组

#include <cstdio>

int main() {
    int x[2][3];
    int y[3][2];
    for (int i = 0; i < 2; i++) {
        for (int j = 0; j < 3; j++) {
            scanf("%d", &x[i][j]);
        }
    }
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 2; j++) {
            scanf("%d", &y[i][j]);
        }
    }
    for (int i = 0; i < 2; i++) {
        printf("%d %d\n", x[i][0]*y[0][0] + x[i][1]*y[1][0] + x[i][2]*y[2][0],
               x[i][0]*y[0][1] + x[i][1]*y[1][1] + x[i][2]*y[2][1]);
    }

    return 0;
}

7.ZOJ (简单)
提交网址:https://www.nowcoder.com/practice/7557d470617c464f9200d93acf721471
在这里插入图片描述

#include <cstdio>
#include <iostream>
#include <string>
using namespace std;

int main(){
    string ZOJ;
    int Z = 0,O = 0,J = 0;
    while(cin>>ZOJ){
        int len = ZOJ.size();
        for(int i = 0; i < len; ++i){
            if(ZOJ[i] == 'Z') Z++;
            if(ZOJ[i] == 'O') O++;
            if(ZOJ[i] == 'J') J++;
        }
        //按照ZOJ顺序输出
        while(Z>0 || O>0 || J>0){
            if(Z>0){
                cout << "Z";
                Z--;
            }
            if(O>0){
                cout << "O";
                O--;
            }            
            if(J>0){
                cout << "J";
                J--;
            }              
        }
        cout<<endl;
    }
    return 0;
}

8.日期类(中等)

提交网址
在这里插入图片描述

解法1:纯模拟

#include <stdio.h>
#include <stdbool.h>

void nextDay(int year,int month,int day){
    int dayOfMonth[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
    bool isLeap = (year%400 == 0) || (year%4 ==0 && year%100 != 0);
    if(isLeap)  dayOfMonth[2] = 29;
    day++;
    if(day > dayOfMonth[month]){
        day = 1;
        month++;
    }
    if(month > 12){
        month = 1;
        year++;
    }

    printf("%04d-%02d-%02d\n",year,month,day);
}

int main(void){
    int n;
    scanf("%d",&n);

    int year,month,day;
    for(int i = 0; i < n; ++i){
        scanf("%d%d%d",&year,&month,&day);
        nextDay(year,month,day);
    }

    return 0;
}

2.格式化输入输出: scanf("%4d") 只读取4个长度的int



2.排序

1.小白鼠排队
提交网址:https://www.nowcoder.com/practice/27fbaa6c7b2e419bbf4de8ba60cf372b
在这里插入图片描述

1.sort(arr,arr+n,comp)

解法1:结构体+排序(结构体数组+自定义排序规则)

#include <cstdio>
#include <string>
#include <algorithm>
using namespace std;

struct Mouse{
    int weight;
    string color;
};

bool comp(Mouse lhs,Mouse rhs){
    return lhs.weight>rhs.weight;
}

int main(){
    int n;
    scanf("%d",&n);
    int weight;
    char color1[100];
    Mouse arr[100];
    for(int i = 0; i < n ;++i){
        scanf("%d %s",&weight,color1);
        string color = color1;
        arr[i].weight = weight;
        arr[i].color = color;
    }
    sort(arr,arr+n,comp);
    for(int i = 0; i < n; ++i){
        printf("%s\n",arr[i].color.c_str());
    }
    return 0;
}

解法2:map自动排序

#include <cstdio>
#include <map>
#include <string>
#include <utility>
using namespace std;

map<int,string,greater<int>> Mouse;

int main(){
    int n;
    scanf("%d",&n);
    int weight;
    char color[100];
    for(int i = 0; i < n; ++i){
        scanf("%d %s",&weight,color);
        string color1 = color;
        Mouse.insert(pair<int,string>(weight,color1));
    }
    map<int,string>::iterator it;
    for(it = Mouse.begin();it != Mouse.end();++it){
        printf("%s\n",it->second.c_str());
    }
    return 0;
}

2.set

2.Simple Sorting
题目大义:给一串数字,去重后进行排序
在这里插入图片描述
提交网址:https://www.nowcoder.com/practice/139761e0b59a405786898b7f2db9423f

解法:STL之set(自动去重+升序排序)

#include <cstdio>
#include <iostream>
#include <set>
using namespace std;

int main(){
    int n;
    while(scanf("%d",&n) != EOF){
        int a;
        set<int> num;
        for(int i = 0; i < n; ++i){
            scanf("%d",&a);
            num.insert(a);
        }
        set<int>::iterator it;
        for(it = num.begin();it != num.end();++it){
            cout<<*it<<" ";
        }
        printf("\n");
    }
    return 0;
}

3.寻找大富翁
在这里插入图片描述
提交网址:https://www.nowcoder.com/practice/38131e23663746a992581d45f16e7a86

#include <cstdio>
#include <algorithm>
using namespace std;

bool comp(int lhs, int rhs) {
    return lhs > rhs; //降序排序
}

int main() {
    int n, m;
    while (scanf("%d %d", &n, &m) != EOF) {
        int arr[n];
        for(int i = 0; i < n; ++i){
            scanf("%d", &arr[i]);
        }
        sort(arr, arr + n, comp);
        if (n>m) {
            for(int i = 0; i < m; ++i){
                printf("%d ",arr[i]);
            }
            printf("\n");
        }else{ //n<m
            for(int i = 0; i < n; ++i){
                printf("%d ",arr[i]);
            }
            printf("\n");
        }
    }
    return 0;
}

4.成绩排序
提交网址
在这里插入图片描述
易错点(bug原因):C字符数组不能直接比较大小,只有C++的string才可以直接比大小。

#include <cstdio>
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;

struct Student{
    string name;
    int age;
    int grade;
};

bool comp(Student lhs, Student rhs){
    if(lhs.grade < rhs.grade){ //1.按成绩
        return true;
    }else if(lhs.grade == rhs.grade && lhs.name < rhs.name){ //2.按名字
        return true;
    }else if(lhs.grade == rhs.grade && lhs.name == rhs.name && lhs.age < rhs.age){//3.按年龄
        return true;
    }else{
        return false;
    }
}

int main(){
    int n;
    while(scanf("%d",&n) != EOF){
        Student stu[n+1];
        for(int i = 0; i < n; ++i){
            char cname[101];
            scanf("%s %d %d",&cname,&stu[i].age,&stu[i].grade);
            stu[i].name = cname;
        }
        sort(stu,stu+n,comp);
        for(int i = 0; i < n; ++i){
            printf("%s %d %d\n",stu[i].name.c_str(),stu[i].age,stu[i].grade);
        }
    }
    return 0;
}

5.成绩排序(困难,实际中等)
提交网址:http://t.cn/E9gyHM1
在这里插入图片描述
解题思路:结构体里还需要保存 输入的次序 order,以便在成绩相同时按order升序排序

#include <cstdio>
#include <algorithm>
#include <string>
using namespace std;

struct Student{
    string name;
    int grade;
    int order; //输入的次序
};

bool comp0(Student lhs,Student rhs){ //按成绩降序
    if(lhs.grade > rhs.grade){
        return true;
    }else if(lhs.grade == rhs.grade){
        return lhs.order < rhs.order;
    }else{
        return false;
    }
}

bool comp1(Student lhs,Student rhs){ //按成绩升序
    if(lhs.grade < rhs.grade){
        return true;
    }else if(lhs.grade == rhs.grade){
        return lhs.order < rhs.order;
    }else{
        return false;
    } 
}

int main(){
    int n,rule;
    while(scanf("%d %d",&n,&rule) != EOF){
        //1.输入
        Student stu[n]; //申请长度为n的结构体数组
        for(int i = 0; i < n; ++i){
            char cname[100];
            scanf("%s %d",cname,&stu[i].grade);
            stu[i].name = cname; //C字符数组转string
            stu[i].order = i; //保存输入的次序,便于在成绩相同时,按order升序排序
        }
        
        //2.排序
        if(rule == 0){ //降序
            sort(stu,stu+n,comp0);
        }else{ //rule ==1,升序
            sort(stu,stu+n,comp1);
        }

        //3.输出
        for(int i = 0; i < n; ++i){
            printf("%s %d\n",stu[i].name.c_str(),stu[i].grade);
        }
    }
    return 0;
}



3.查找

1.找x (数组)
提交网址:https://www.nowcoder.com/practice/069e2130430c41229ab25e47fa0949a6
在这里插入图片描述

#include <cstdio>

int main(){
    int n;
    scanf("%d",&n);
    int arr[300];
    for(int i =0;i < n; ++i){
        scanf("%d",&arr[i]);
    }
    int x;
    scanf("%d",&x);
    bool flag = false;
    for(int i =0; i < n; ++i){
        if(arr[i] == x){
            printf("%d",i);
            flag = true;//找到了
        }
    }
    if(flag == false){//没找到
        printf("-1");
    }
    return 0;
}

2.求最大最小数
在这里插入图片描述
提交网址:https://www.nowcoder.com/practice/82e5ff335eeb486aab359767895cc7b4

#include <cstdio>
#include <algorithm>
using namespace std;

int main(){
    int n;
    while(scanf("%d",&n) != EOF){
        int arr[n];
        for(int i =0 ;i < n; ++i){
            scanf("%d",&arr[i]);
        }
        sort(arr,arr+n);
        printf("%d %d\n",arr[n-1],arr[0]);

    }
    return 0;
}

3.开门人和关门人
提交网址:https://www.nowcoder.com/practice/a4b37b53a44d454ab0834e1517983215
在这里插入图片描述

#include <iostream>
#include <string>
using namespace std;

int main(){
    int n;
    while(cin >> n){
        string id,signIn,signOut;
        string openId,closeId;
        string signInTime = "24:00:00",signOutTime = "00:00:00";
        for(int i = 0; i < n; ++i){
            cin >> id >> signIn >> signOut;
            //最早来
            if(signIn < signInTime){
                signInTime = signIn;
                openId = id;
            }
            //最晚走
            if(signOut > signOutTime){
                signOutTime = signOut;
                closeId = id;
            }
        }
        cout << openId << " " << closeId<<endl;
    }
    return 0;
}

4.查找 (Easy)
提交网址在这里插入图片描述

#include <cstdio>

int main(){
    int n;
    while(scanf("%d",&n) != EOF){
        int arr[n];
        for(int i = 0; i < n ; ++i){
            scanf("%d",&arr[i]);
        }
        int m;
        int target;
        scanf("%d",&m);
        for(int i = 0; i < m; ++i){
            scanf("%d",&target);
            
            //顺序查找
            int flag = false;
            for(int i = 0; i < n; ++i){
                if(arr[i] == target){
                    flag = true;
                } 
            }

            if(flag){ //找到了
                printf("YES\n");
            }else{
                printf("NO\n");
            }
        }
    }
    return 0;
}

1.结构体数组

struct Student{
    int Number;
    char Name[100];
    char sex[20];
    int age;
};

int n;
scanf("%d",&n);
Student stu[n];
for(int i = 0; i < n; ++i){
    scanf("%d %s %s %d",&stu[i].Number,&stu[i].Name,&stu[i].sex,&stu[i].age);
}

5.学生查询(中等)
提交网址
在这里插入图片描述

#include <cstdio>

struct Student{
    int Number;
    char Name[100];
    char sex[20];
    int age;
};

int main(){
    int m;
    scanf("%d",&m);
    for(int i = 0; i < m; ++i){
        int n;
        scanf("%d",&n);
        Student stu[n+1];
        for(int i = 1; i <= n; ++i){
            scanf("%d %s %s %d",
                  &stu[i].Number,&stu[i].Name,&stu[i].sex,&stu[i].age);
        }
        int id;
        scanf("%d",&id);
        printf("%d %s %s %d\n",
                  stu[id].Number,stu[id].Name,stu[id].sex,stu[id].age);
    }
    return 0;
}

6.找最小数
提交网址:https://www.nowcoder.com/practice/ba91786c4759403992896d859e87a6cd
在这里插入图片描述
解法1:结构体数组+sort

#include <cstdio>
#include <algorithm>
using namespace std;

struct XY{
    int x;
    int y;
};

bool comp(XY lhs,XY rhs){
    if(lhs.x < rhs.x){
        return true;
    }else if(lhs.x == rhs.x && lhs.y < rhs.y){
        return true;
    }else{
        return false;
    }
}

int main(){
    int n;
    scanf("%d",&n);
    XY arr[2000];//结构体数组
    for(int i = 0 ; i < n; ++i){
        scanf("%d %d",&arr[i].x,&arr[i].y);
    }
    sort(arr,arr+n,comp);//结构体数组排序
    printf("%d %d",arr[0].x,arr[0].y);
    return 0;
}



4.字符串

1.字符串排序
提交地址
在这里插入图片描述

#include <iostream>
#include <string>
#include <algorithm>
using namespace std;

int main() {
    string str;
    while (cin >> str) { 
        sort(str.begin(),str.end());
        cout <<str<< endl;
    }
    return 0;
}



2.后缀子串排序
提交网址
在这里插入图片描述

#include <iostream>
#include <string>
#include <algorithm>
using namespace std;

int main(){
    string str;
    cin >> str;
    int len = str.length();
    string arr[100];
    for(int i = 0; i < len ; ++i){
        arr[i] = str.substr(i);
    }
    sort(arr,arr+len);//对整个string数组内排序
    for(int i = 0; i < len; ++i){
        cout<<arr[i]<<endl;
    }
    return 0;
}

3.(字符)数组逆置
提交网址:https://www.nowcoder.com/practice/b4f598480524493aae4686947fbf31dc
在这里插入图片描述

#include <cstdio>
#include <string>
using namespace std;

int main(){
    char arr[300];
    while(scanf("%s",arr) != EOF){
        string str = arr;
        int len = str.size();
        for(int i = 0; i < len; ++i){
            printf("%c",str[len-i-1]);   
        }
        printf("\n");
    }
    return 0;
}

1.string和int的相互转换

①int转string:to_string(i)

	int a;
    while(scanf("%d",&a) != EOF){
        string str = to_string(a);
        printf("%s",str.c_str());
    }

②string转int:stoi(str)

#include <string>
int a = stoi(sa);


4.守型数
提交网址:https://www.nowcoder.com/practice/99e403f8342b4d0e82f1c1395ba62d7b
在这里插入图片描述

#include <cstdio>
#include <string>
using namespace std;

int main(){
    int a;
    while(scanf("%d",&a) != EOF){
        string s = to_string(a);
        string str = to_string(a*a);
        int len = str.length();
        string sub = str.substr(len/2);//无论奇数位偶数位,低位起始位置都是len/2
        if(s == sub){
            printf("Yes!\n");
        }else{
            printf("No!\n");
        }
    }
    return 0;
}

5.字符串链接
在这里插入图片描述

提交网址:https://www.nowcoder.com/practice/9f27c74ec91e4c7da96ba351dba235fc
解题思路:用string里的 + 完成字符串拼接

#include <cstdio>
#include <string>
using namespace std;

int main(){
    char a[100];
    char b[100];
    while(scanf("%s %s",a,b) != EOF){
        string sa = a;
        string sb = b;
        string str = sa+sb;
        printf("%s\n",str.c_str());
    }
    return 0;
}

2.map[key]++

map[i]++
①若map中没有为key = i的键,则先insert <key = i,0>,然后value++。最终map中存入<key = i,1>。
②若map中已有key = i,则value++

#include <cstdio>
#include <map>
#include <iostream>
using namespace std;

int main() {
    map<int, int> myMap;
    for (int i = 0; i < 5; i++) {
        myMap[i]++;
    }
    for (auto it = myMap.begin(); it != myMap.end(); it++) {
        cout << '<'<< it->first << ',' << it->second <<'>'<< endl;
    }

    cout<<"第二轮"<<endl;
    for (int i = 0; i < 5; i++) {
        myMap[i]++;
    }
    for (auto it = myMap.begin(); it != myMap.end(); it++) {
        cout << '<'<< it->first << ',' << it->second <<'>'<< endl;
    }
    return 0;
}

6.子串计算
在这里插入图片描述
提交网址:https://www.nowcoder.com/practice/bcad754c91a54994be31a239996e7c11

#include <cstdio>
#include <string>
#include <map>
using namespace std;

int main(){
    map<string,int> myMap;
    char arr[101];
    scanf("%s",arr);
    string str = arr;
    int len = str.size();
    for(int i = 0; i <len; ++i){
        for(int j = i; j < len; ++j){//难点
            string s = str.substr(i,j-i+1);//难点
            myMap[s]++;//重点 map[i]++
        }
    }
    map<string,int>::iterator it;
    for(it = myMap.begin();it != myMap.end();++it){
        if(it->second > 1){ //输出:出现次数至少2次的子串
            printf("%s %d\n",it->first.c_str(),it->second);
        }
    }
    return 0;
}

7.谁是你的潜在朋友
提交网址
在这里插入图片描述

#include <cstdio>
#include <map>
#include <utility>
using namespace std;

int main(){
    int n,m; //n个读者,m本书
    while(scanf("%d %d",&n,&m) != EOF){
        //存入
        int book[201];    //i读者喜欢的书号为 book[i]
        map<int,int> mymap; //书号->喜欢该书的人数
        for(int i = 0; i < n; ++i){
            scanf("%d",&book[i]);
            mymap[book[i]]++; //核心
        }

        //读取
        for(int i = 0; i < n; ++i){
            if(mymap[book[i]] > 1){
                printf("%d\n",(mymap[book[i]])-1);//有几个朋友,不包括自己
            }else{
                printf("BeiJu\n");
            }
        }
    }
    return 0;
}


3.getline()

1.getline()的两种分类
①以换行符 ‘\n’ 结束字符串的读入:getline(cin,str)
②以一个字符来结束字符串的读入:getline(cin ,string str ,char ch)

2.字符串的输入中,getline与cin的区别
①cin遇到空格代表字符串输入结束
②getline遇到换行符代表字符串输入结束


1.①getline(cin,s)

#include<iostream>
#include<string>
using namespace std;

int main(){
    string s;
    cout<<"输入字符串:";
    getline(cin,s);
    cout<<"输出字符串:";
    cout<<s;
    return 0;
}

1.②getline(cin,str,'c')

#include<iostream>
#include<string>
using namespace std;

int main(){
    string str;
    cout<<"输入字符串:";
    getline(cin,str,'c');
    cout<<"输出字符串:";
    cout<<str;
    return 0;
}

8.密码翻译
在这里插入图片描述
提交网址:https://www.nowcoder.com/practice/136de4a719954361a8e9e41c8c4ad855

#include <cstdio>
#include <iostream>
#include <string>
using namespace std;

int main(){
    string str;
    while(getline(cin,str)){
        int len = str.length();
        for(int i =0; i < len; ++i)
        {   //大写
            if('A' <= str[i] && str[i] <= 'Z'){
                if(str[i] == 'Z'){
                    str[i] = 'A';
                }else{
                    str[i] = str[i]+1;
                }
            }
            //小写
            if('a' <= str[i] && str[i] <= 'z'){
                if(str[i] == 'z'){
                    str[i] = 'a';
                }else{
                    str[i] = str[i]+1;
                }
            }            
        }
        printf("%s\n",str.c_str());
    }
    return 0;
}

getline(cin,str)一行字符串后,基于空格分割单词

9.单词替换
提交网址
在这里插入图片描述

我的解题思路:
①getline读入一整行,遍历s以空格为界,分割单词,存入vector。
②遍历vector[i]进行字符串替换
③遍历输出vector

#include <cstdio>
#include <iostream>
#include <string>
#include <vector>
using namespace std;

int main(){
    string s;
    while(getline(cin,s)){ //1.读入一整行
        string a,b;
        cin>>a>>b;
        vector<string> vec;
        //2.分割一整行为一个个的单词,存入vector
        string sub = ""; //初始为空
        for(int i = 0; i < s.size(); ++i){
            if(s[i] != ' '){
                sub += s[i];
            }else{
                vec.push_back(sub);
                sub.clear();
            }
            if(i == s.size()-1){  //存入最后一个单词
                vec.push_back(sub);
                sub.clear();                
            }
        }
        //3.替换
        for(int i = 0; i < vec.size(); ++i){
            if(vec[i] == a){
                vec[i] = b;
            }
        }
        //4.遍历输出
        vector<string>::iterator it;
        for(it = vec.begin();it != vec.end(); ++it){
            cout<<*it<<" ";
        }
    }
    return 0;
}

10.首字母大写
提交网址
在这里插入图片描述
解题思路:用getline(cin,str)读入一行。用空白符分割单词,判断是否为单词的首字母

#include <cstdio>
#include <iostream>
#include <string>
using namespace std;

int main(){
    string str;
    while(getline(cin,str)){
        if('a' <= str[0] && str[0] <= 'z')  str[0] = str[0]-32;
        cout<<str[0];

        for(int i = 1; i < str.length(); ++i){
            if(str[i]==' ' || str[i]=='\t' ||  str[i]=='\r' || str[i]=='\n'){
                if('a' <= str[i+1] && str[i+1] <= 'z')  str[i+1] = str[i+1]-32;
            }
            cout<<str[i];
        }
    }
    return 0;
}

4.ASCII码表

A:65
Z:90
a:97
z:122

在这里插入图片描述


9.简单密码
题目大意:密文→明文(A→V,B→W,C→X,D→Y,E→Z,F→A,G→B)

在这里插入图片描述
提交网址:https://www.nowcoder.com/practice/ff99c43dd07f4e95a8f2f5448da3772a

#include <cstdio>
#include <iostream>
#include <string>
using namespace std;

int main() {
    string str;
    while (getline(cin, str)) {
        if (str == "ENDOFINPUT") break;
        if (str == "START") {   //读取正文
            getline(cin, str);
            for(int i = 0; i < str.length(); ++i){
                if('A' <= str[i] && str[i] <= 'Z'){ //限定只有大写字母转换
                    str[i] = (str[i] - 5 - 'A' + 26) % 26 + 'A'; //密文转明
                }
            }
            cout << str << endl;
        }
        getline(cin, str); //吃掉END
    }
    return 0;
}

10.反序输出
在这里插入图片描述
提交网址:https://www.nowcoder.com/practice/171278d170c64d998ab342b3b40171bb

#include <cstdio>
#include <string>
using namespace std;

int main(){
    char arr[5];
    char str[5];
    while(scanf("%s",arr) != EOF){
        for(int i = 0; i < 4; ++i){
            str[3-i] = arr[i];
        }
        printf("%s\n",str);
    }
    return 0;
}

<



11.字母统计 (Easy)
提交网址
在这里插入图片描述

#include <cstdio>
#include <iostream>
#include <string>
#include <cstring>
using namespace std;

int main(){
    string str;
    while(getline(cin,str)){
        int len = str.size();
        int count[26];
        memset(count,0,sizeof(count));
        for(int i = 0; i < len; ++i){
            if('A' <= str[i] && str[i] <= 'Z'){
                count[str[i]-'A']++; //核心
            }
        }
        for(int i = 0;i < 26; ++i){
            printf("%c:%d\n",'A'+i,count[i]);
        }
    }
    return 0;
}


6.getchar() //吃掉回车

读行之前如果出现过cin或scanf,一定要把最后一个回车换行给吞掉,不然输入会出错

12.字符串排序
提交网址
在这里插入图片描述

解题思路:
①用vec保存各字符串(用getchar()吃掉输入时缓存的回车)
②用sort进行排序(自定义comp规则为按照长度排序)
③遍历输出

#include <cstdio>
#include <iostream> //getline(cin,str)
#include <string>
#include <vector>
#include <algorithm>  //sort()
using namespace std;

bool comp(string &lhs,string &rhs){
    return lhs.length()<rhs.length();
}

int main(){
    int n;
    string str;
    while(scanf("%d",&n) != EOF){
        //1.读入
        getchar(); //吞回车
        vector<string> vec;
        for(int i = 0; i < n; ++i){
            getline(cin,str); //一行行读入
            if(str == "stop")   
                break;
            vec.push_back(str);
        }
        //2.排序
        sort(vec.begin(),vec.end(),comp);
        //3.输出
        vector<string>::iterator it;
        for(it = vec.begin();it != vec.end(); ++it){
            printf("%s\n",it->c_str());
        }
    }
    return 0;
}

13.字符串去特定字符
提交网址
在这里插入图片描述

#include <cstdio>
#include <string.h>
using namespace std;

int main(){
    char s[500],c;
    while(scanf("%s",s) != EOF){
        getchar(); //吃掉回车。避免scanf读入\n
        scanf("%c",&c);
        int len = strlen(s);
        for(int i = 0; i < len; ++i){
            if(s[i] != c){
                printf("%c",s[i]);
            }
        }
        printf("\n");
    }
    return 0;
}

14.合并符串
提交网址
在这里插入图片描述

#include <cstdio>
#include <string>
using namespace std;

int main(){
    char s1[101];
    char s2[101];
    while(scanf("%s %s",s1,s2) != EOF){
        string str1 = s1;
        string str2 = s2;
        int len = str1.length();
        for(int i = 0; i < len; ++i){
            printf("%c%c",str1[i],str2[len-1-i]);//一个字符一个字符遍历输出
        }
    }
    return 0;
}

7.用vector保存多个字符串

vector<string> vec;

15.最长最短文本
提交网址
在这里插入图片描述

#include <cstdio>
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;

bool comp(string lhs,string rhs){
    return lhs.length() < rhs.length();
}

int main(){
    vector<string> vec;
    string str;
    while(getline(cin,str)){
        vec.push_back(str);
    }

    sort(vec.begin(),vec.end(),comp);//按字符串长度递增排序

    int maxlen = 0,minlen = 1000;
    vector<string>::iterator it;
    for(it = vec.begin();it != vec.end();++it){
        if((*it).length() > maxlen)   maxlen = it->length();
        if((*it).length() < minlen)   minlen = it->length();
    }

    for(it = vec.begin();it != vec.end();++it){
        if(it->length() == minlen || it->length() == maxlen){
            cout<<*it<<endl;
        }
    }
    return 0;
}

16.编排字符串
提交网址
在这里插入图片描述

#include <cstdio>
#include <iostream>
#include <string>
#include <vector>
using namespace std;

int main(){
    int m;
    while(scanf("%d",&m) != EOF){
        string str;
        vector<string> vec;
        for(int i = 0;i < m; ++i){
            cin>>str;
            vec.insert(vec.begin(),str); //vector头部插入字符串
            for(int j = 0; j < vec.size() && j <4; ++j){ 
                cout<<j+1<<"="<<vec[j]<<" ";
            }
            cout<<endl;
        }
    }
    return 0;
}


8.swap()函数

头文件

#include <iostream>
using namespace std;

swap也可以交换字符串

#include <cstdio>
#include <iostream>
using namespace std;

int main(){
    char ch[2]={'a','b'};
    swap(ch[0],ch[1]);
    printf("%c %c",ch[0],ch[1]);
    return 0;
}

9.string之erase()

17.A+B
提交网址
在这里插入图片描述

#include <cstdio>
#include <iostream>
#include <string>
using namespace std;

int main(){
    string sa,sb;
    while(cin>>sa>>sb){
        string::iterator it;
        for(it=sa.begin();it!=sa.end();++it){
            if(*it == ','){
                sa.erase(it);
            }
        }
        for(it=sb.begin();it!=sb.end();++it){
            if(*it == ','){
                sb.erase(it); //删除逗号
            }
        }
        int a,b;
        a = stoi(sa);
        b = stoi(sb);
        printf("%d\n",a+b);
    }
    return 0;
}

### 10.大写转小写 (手动实现)
#include <cstdio>
#include <iostream>
#include <string>
using namespace std;

string tolower(string str){
    for(int i = 0; i < str.size(); ++i){
        if('A' <= str[i] &&str[i] <= 'Z'){ //大写转小写
            str[i] = str[i]+32;
        }
    }
    return str;
}

int main(){
    string str = "Ab1";
    str = tolower(str);
    cout <<str;
    return 0;
}



5.数学问题

1.进制转换

例题1:10进制 → 2进制
提交网址:http://t.cn/AiCuKTOv

解法1:用int / long long int保存结果
缺点:保存长度有限,尤其是目标结果是二进制
改进:用vector保存结果,改进:用vector保存结果,见解法2

#include <cstdio>
#include <cmath>

int main(){
    unsigned int n;
    while(scanf("%d",&n) != EOF){
        //10进制 → 2进制
        long long int remain = 0, res = 0, mi = 0;
        while(n>0){   //短除法
            remain = n%2;
            n /= 2;
            res = res + remain*pow(10,mi);
            mi++;
        }
        printf("%lld\n",res);
    }
    return 0;
}

解法2:用vector保存二进制数

#include <cstdio>
#include <vector>
using namespace std;

int main(){
    unsigned int n;
    while(scanf("%d",&n) != EOF){
        //10进制 → 2进制
        vector<int> binary;
        int remain = 0;
        while(n>0){
            remain = n%2;
            binary.push_back(remain);
            n /= 2;
        }
        // vector<int>::iterator it; 
        // for(it = vec.end()-1;it !=vec.begin()-1;--it){ //迭代器遍历
        //     printf("%d",*it);
        // }
        for(int i = binary.size()-1; i >=0; --i){
            printf("%d",binary[i]);  //下标访问遍历
        }
        printf("\n");
    }
    return 0;
}

例题2:10进制 → 8进制
提交网址:http://t.cn/AiCu01He

#include <cstdio>
#include <vector>
using namespace std;

int main(){
    int n;
    while(scanf("%d",&n) != EOF){
        vector<int> vec;
        int remain = 0;
        while(n>0){
            remain = n%8;
            vec.push_back(remain);
            n /= 8;
        }
        for(int i = vec.size()-1; i >= 0 ; --i){
            printf("%d",vec[i]);
        }
        printf("\n");
    }
    return 0;
}

例题3:10进制 →m进制
提交网址:http://t.cn/AiCuOSWv
在这里插入图片描述

#include <cstdio>
#include <vector>
using namespace std;

int main(){
    int m,A,B;
    while(scanf("%d%d%d",&m,&A,&B) != EOF){
        //边界条件
        if(m ==0)  break;
        if(A == 0 && B ==0){
            printf("0\n");
            break;
        }
        //10进制 -> m进制
        vector<int> vec;
        long long int n = A+B, remain = 0;
        while(n>0){
            remain = n%m;
            vec.push_back(remain);
            n /= m;
        }
        for(int i = vec.size()-1; i >=0 ; --i){
            printf("%lld",vec[i]);
        }
        printf("\n");
    }
    return 0;
}

例题4:16进制 -> 10进制
提交网址:http://t.cn/AiCuig9B

#include <iostream>
#include <string>
using namespace std;

int main(){
    string str;
    while(cin>>str){
        int res = 0,remain = 0;   //初始化清零条件要放在while里面
        for(int i = 2; i < str.size(); ++i){//从2起,去掉0x
            if('0'<=str[i] && str[i]<='9'){
                remain = str[i]-'0'; 
            }else{
                remain = str[i]-'A'+10; //A代表10
            }
            res = res*16 + remain;
        }
        printf("%d\n",res);
    }
    return 0;
}



2.大数问题(长整型)

int :最多支持10位
long long int:最多支持19位



1.阶乘问题
int 最多可计算12!
long long int 最多可计算20!
n超过20就是大数运算了,需要借助数组



例题1:大整数排序
提交网址
在这里插入图片描述
解题思路:用string数组来保存大整数(多个字符串),编写sort的排序规则comp:①先比长度 ②长度相同比大小(string可以直接比大小,从最高位用ASCII码比)

#include <iostream>
#include <string>
#include <algorithm>
using namespace std;

bool comp(string lhs, string rhs){
    if(lhs.size() < rhs.size()){
        return true;
    }else if(lhs.size() == rhs.size() && lhs < rhs){
        return true;
    }
    else{
        return false;
    }
}

int main(){
    int n;
    while(scanf("%d",&n) != EOF){
        string str[101];  //使用string数组来保存多个字符串
        for(int i = 0; i < n; ++i){
            cin>>str[i];
        }
        sort(str,str+n,comp);
        for(int i = 0; i < n; ++i){
            cout<<str[i]<<endl;
        }
    }
    return 0;
}



3.求a^b:pow(a,b)

#include <cmath>

pow(a,b);

4.求最大公约数

辗转相除法:
//greatest comon divisor

int gcd(int a, int b){//欧几里得算法求最大公约数
    if(b==0)  return a;
    else      return gcd(b, a%b);
}

三目运算符
表达式1 ? 表达式2 : 表达式3;
若1为真,则执行2;若1为假,则执行3;



1.求最大公约数
提交网址:https://www.nowcoder.com/practice/20216f2c84bc438eb5ef05e382536fd3
在这里插入图片描述

解:gcd()函数

#include <iostream>
using namespace std;

int gcd(int a,int b){
    if(b==0) return a;
    else     return gcd(b,a%b);
}

int main(){
    int a,b;
    cin >> a >> b;
    cout << gcd(a,b);
    return 0;
}



2.最简真分数
在这里插入图片描述
提交网址:https://www.nowcoder.com/practice/1f1db273eeb745c6ac83e91ff14d2ec9

#include <cstdio>

int gcd(int a, int b){ //辗转相除法 求最小公因数
    return b ? gcd(b, a % b) : a;
}

int main(){
    int n;
    while(scanf("%d",&n) != EOF){
        if(n == 0) break;
        int arr[n];
        for(int i = 0; i < n; ++i){
            scanf("%d",&arr[i]);
        }
        int count = 0;
        for(int i = 0; i < n; ++i){
            for(int j = i+1; j < n; ++j){
                if(arr[j] % arr[i] != 0 ){  //真分数,分母不是分子的倍数
                    if(gcd(arr[i],arr[j]) == 1){   //也不能有公因子
                        count++;         
                    }
                    
                } 
            }
        }
        printf("%d\n",count);
    }
    return 0;
}


3.百万富翁问题
提交网址:https://www.nowcoder.com/practice/9fe25b6cf93e46dcb09ba67aeef2c4cc
在这里插入图片描述


4.数字求和
提交网址:https://www.nowcoder.com/practice/e8cee01f2d834fa9ba3479fafe492b65
在这里插入图片描述

#include <cstdio>

int main(){
    int a;
    int arr[5];
    while(scanf("%d",&a) != EOF){
        for(int i = 0; i < 5; ++i){
            scanf("%d",&arr[i]);
        }
        int sum = 0;
        for(int i = 0; i < 5; ++i){
            if(arr[i] < a){
                sum += arr[i];
            }
        }
        printf("%d",sum);
    }
    return 0;
}

5.n的阶乘(简单)
提交网址:https://www.nowcoder.com/practice/97be22ee50b14cccad2787998ca628c8
在这里插入图片描述

#include <cstdio>

long long int Factorial(int n){
    if(n == 0){
        return 1;
    }else{
        return n*Factorial(n-1);
    }
}

int main(){
    int n;
    while(scanf("%d",&n) != EOF){
        printf("%lld",Factorial(n));
    }
    return 0;
}

6.阶乘(中等)
提交网址
在这里插入图片描述
解法1:我的朴素实现(46行)

#include <cstdio>

long long int Factorial(int n){
    if(n == 0 || n == 1){
        return n;
    }else{
        return n*Factorial(n-1);
    }
}

long long int sy1(int m){
    int y1 = 0;
    while(m > 0){
        y1 += Factorial(m);
        m = m-2;
    }
    return y1;
}

long long int sy2(int p){
    int y2 = 0;
    while(p > 0){
        y2 += Factorial(p);
        p = p-2;
    }
    return y2;
}

int main(){
    int n;
    while(scanf("%d",&n) != EOF){
        //判断n是奇数还是偶数
        int m,p,y1,y2;
        if(n%2 ==0){ //偶数
            m = n-1;
            p = n;
        }else{ //奇数
            m = n;
            p = n-1;   
        }
        y1 = sy1(m);
        y2 = sy2(p);
        printf("%lld %lld",y1,y2);
    }
    return 0;
}

解法2:大佬的简介实现(15行)

#include <iostream>
using namespace std;
int main()
{
    int n ,ans1, ans2, i, j;
    while (cin >> n) {
        ans1 = ans2 = 0, j = 1;
        for (i = 1; i <= n; ++i) {
            j *= i; // j = i!
            if(i % 2)  ans1 += j; //奇数的阶乘之和
            else       ans2 += j; //偶数的阶乘之和
        }
        cout << ans1 << " " << ans2 << endl;
    }
}

7.特殊乘法
在这里插入图片描述
提交网址:https://www.nowcoder.com/practice/a5edebf0622045468436c74c3a34240f

解题思想:实际上是求各位数之和,再相乘。只需要构造一个能求各位之和的函数即可。可参考求逆序数的Reverse函数求法。

#include <cstdio>

int Add(int n){ //各位数之和
    int sum = 0;
    while(n != 0){
        int remain = n%10;
        sum += remain;
        n /= 10;
    }
    return sum;
}

int main(){
    int a,b;
    while(scanf("%d%d",&a,&b) != EOF){
        printf("%d\n",Add(a)*Add(b));
    }
    return 0;
}

8.三角形的边
在这里插入图片描述
提交网址:https://www.nowcoder.com/practice/05dbd1cd43b24dbbae567b3e816d4e97

#include <cstdio>

int main() {
    int a, b, c;
    int min, mid, max;
    while (scanf("%d%d%d", &a, &b, &c) != EOF) {
        if (a == 0 && b == 0 && c == 0) {
            //do nothing
        }else {
            if (a >= b && a >= c && b >= c) {
                max = a;
                mid = b;
                min = c;
            } else if (a >= b && a >= c && b <= c) {
                max = a;
                mid = c;
                min = b;
            } else if (b >= a && b >= c && a >= c) {
                max = b;
                mid = a;
                min = c;
            } else if (b >= a && b >= c && a <= c) {
                max = b;
                mid = c;
                min = a;
            } else if (c >= a && c >= b && a >= b) {
                max = c;
                mid = a;
                min = b;
            } else if (c >= a && c >= b && a >= b) {
                max = c;
                mid = a;
                min = b;
            } else if (c >= a && c >= b && a <= b) {
                max = c;
                mid = b;
                min = a;
            }
            printf("%d\n", min + mid - max);
        }
    }
    return 0;
}

9.求平均年龄
在这里插入图片描述
提交网址:https://www.nowcoder.com/practice/ca319fdb02714994850cc631d76f5547

#include <cstdio>

int main(){
    int n;
    while(scanf("%d",&n) != EOF){
        int age;
        float sum = 0;
        for(int i =0; i < n; ++i){
            scanf("%d",&age);
            sum += age;
        }
        float num = sum/n;
        printf("%0.2f",num);
    }
    return 0;
}

11.鸡兔同笼
在这里插入图片描述
提交网址:https://www.nowcoder.com/practice/fda725b4d9a14010bb145272cababef1

#include <cstdio>

int main(){
    int n;
    while(scanf("%d",&n) != EOF){
        if(n == 2){ //n为2
            printf("1 1\n");
        }else if(n%2 != 0){  //n为奇数
            printf("0 0\n");
        }else if(n %4 == 0){ //n为4的倍数
            printf("%d %d\n",n/4,n/2);
        }else{
            printf("%d %d\n",n/4+1,n/2);
        }
    }
    return 0;
}

12.求最大值(中等)
提交网址
解法1:用中的max({a,b,c})函数求多个数中的最大值

#include <cstdio>
#include <algorithm>
using namespace std;

int main(){
    int a1,a2,a3,a4,a5,a6,a7,a8,a9,a10;
    int maximum;
    while(scanf("%d%d%d%d%d%d%d%d%d%d",&a1,&a2,&a3,&a4,&a5,&a6,&a7,&a8,&a9,&a10) != EOF){
        maximum = max({a1,a2,a3,a4,a5,a6,a7,a8,a9,a10});
        printf("max=%d",maximum);
    }
    return 0;
}

解法2:数组保存,遍历一遍求最大值

#include <cstdio>

int main(){
    int n;
    while(scanf("%d",&n) != EOF){
        int arr[10];
        int maximum = n; //输入的第一个数为n,默认为当前最大值
        for(int i = 1; i < 10; ++i){
            scanf("%d",&arr[i]);
            if(arr[i] > maximum){
                maximum = arr[i]; //若出现更大的,则代替maximum
            }
        }
        printf("max=%d",maximum);
    }
    return 0;
}

5.求绝对值:abs(i)

#include <cmath>

abs(i);

6.求素数

#include <cstdio>
#include <vector>
using namespace std;

int main(){
    int n;
    while(scanf("%d",&n) != EOF){
        //1.求[2,n]的所有素数
        vector<int> prime;
        for(int i = 2; i < n; ++i){
            int factor = 0; //因子个数
            for(int j = 1; j <= i; ++j){
                if(i%j==0){
                    factor++;
                }
            }
            if(factor <= 2){
                prime.push_back(i);//i是素数
            }
        }
        //2.遍历输出
        vector<int>::iterator it;
        for(it=prime.begin();it!=prime.end();++it){
            printf("%d ",*it);
        }
    }
    return 0;
}

7.完全数

6、28、496、8128、33550336、8589869056 …


例题1:Problem A
提交网址
在这里插入图片描述

解题思路:打表
完全数在数轴上的分布是很稀疏的,对于这种解极少但范围极大的,不要暴力循环,要用打表。
10000以内的完全数只有4个:6、28、496、8128

#include <cstdio>

int main(){
    int a,b;
    while(scanf("%d %d",&a,&b) != EOF){
        int perfectNumber[4] = {6,28,496,8128}; //10^5内的完全数只有4个
        for(int i = 0; i < 4; ++i){
            if(a <= perfectNumber[i] && perfectNumber[i] <= b){
                printf("%d\n",perfectNumber[i]);
            }
        }

    }
}



6.递归、分治

1.斐波那契数列


例题1:Fibonacci
例题网址:http://t.cn/Ai0K3tU5

解法1:递归

#include <cstdio>

int Fibonacci(int n ){
    if(n == 0 || n == 1){
        return n;
    }else{
        return Fibonacci(n-1) + Fibonacci(n-2);
    }
}

int main(){
    int n;
    while(scanf("%d",&n) != EOF){
        printf("%d\n",Fibonacci(n));
    }
    return 0;
}

解法2:动态规划 (循环)

#include <cstdio>

int fib(int n){
    if(n==0 || n==1) return n;
    int sum = 0, n1 = 0, n2= 1; //0,1,1,2,3,5,8,13,21,34,55,89
    for(int i = 2; i <= n; i++){
        sum = n1 + n2;
        n1 = n2;
        n2 = sum;
    }
    return sum;
}

int main(){
    int n;
    scanf("%d", &n);
    int ret = fib(n);
    printf("%d\n",ret);
    return 0;
}



7.动态规划

1.输入n,读取n个数

int n;
while(scanf("%d",&n) != EOF){
	int arr[n];
    for(int i = 0; i < n; ++i){ 
        scanf("%d",&arr[i]);
    }        
}

2.max()、std::max()

1.比较两个数大小 max(a,b);

#include <iostream>
using namespace std;

max(a,b);

2.比较n个数大小 std::max({});

#include <cstdio>
#include <algorithm>
using namespace std;

int main(){
    int a=1,b=2,c=3;
    int max = std::max({a,b,c});
    printf("%d",max);
    return 0;
}

1.最大序列和
提交网址
在这里插入图片描述

#include <cstdio>
#include <iostream>
#include <climits>
using namespace std;

long long int arr[1000001];//堆上,全局数组
long long int  dp[1000001];

long long MaxSubsequence(int n){
    long long maximum = -INT_MAX;//负无穷
    for(int i =0; i < n; ++i){
        if(i ==0){
            dp[i] = arr[i];
        }else{
            dp[i] = max(arr[i],arr[i]+dp[i-1]);//核心
        }
        maximum = max(maximum,dp[i]);//不断更新最大的连续子序列和
    }
    return maximum;
}

int main(){
    int n;
    while(scanf("%d",&n) != EOF){
        for(int i = 0; i < n; ++i){ 
            scanf("%lld",&arr[i]);
        }        
        printf("%lld\n",MaxSubsequence(n));
    }
    return 0;
}

2.最大上升子序列和


例题1
提交网址
在这里插入图片描述

#include <cstdio>
#include <iostream>
using namespace std;

int arr[10001];
int dp[10001];//当前最大递增子序列和

int main(){
    int n;
    while(scanf("%d",&n) != EOF){
        for(int i = 0; i < n; ++i){
            scanf("%d",&arr[i]);
        }
        int answer = 0;
        for(int i = 0; i < n; ++i){
            dp[i] = arr[i];
            for(int j = 0; j < i; ++j){
                if(arr[j] < arr[i]){
                    dp[i] = max(dp[i],dp[j]+arr[i]);//核心
                }
            }
            answer = max(answer,dp[i]);
        }
        printf("%d\n",answer);
    }
    return 0;
}

例题2:拦截导弹
提交网址
在这里插入图片描述

#include <cstdio>
#include <iostream> //max()
using namespace std;

int main(){
    int height[26]; //导弹高度
    int dp[26];     //能拦截的导弹数目
    int n;
    while(scanf("%d",&n) != EOF){
        for(int i = 0; i < n; ++i){
            scanf("%d",&height[i]);
        }
        int answer = 0;
        for(int i = 0; i < n; ++i){
            dp[i] = 1; //初始化为1,最少能拦截第一枚(若是递增就只能拦截一枚)
            for(int j = 0; j < i; ++j){
                if(height[j] >= height[i]){
                    dp[i] = max(dp[i],dp[j] + 1);
                }
            }
            answer = max(answer,dp[i]);
        }
        printf("%d\n",answer);
    }
    return 0;
}



3.最长公共子序列
例题1
提交网址

#include <cstdio>
#include <iostream>
using namespace std;

int dp[1001][1001];

int main(){
    int n,m;
    scanf("%d%d",&n,&m);
    char s1[n];
    char s2[m];
    scanf("%s%s",s1,s2);
    for(int i = 0; i <= n; ++i){ //前多少个,0~n 共n+1个
        for(int j = 0; j <= m; ++j){ //前多少个,0~m 共m+1个
            if(i==0 || j==0){ 
                dp[i][j] = 0;
                continue;
            }
            //核心4句
            if(s1[i-1] == s2[j-1]){          
                dp[i][j] = dp[i-1][j-1] + 1; 
            }else{  //if(s1[i-1] != s2[j-1])  
                dp[i][j] = max(dp[i-1][j],dp[i][j-1]);
            }
        }
    }
    printf("%d\n",dp[n][m]);
    return 0;
}

例题2:Coincidence
提交网址
在这里插入图片描述

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;

int main(){
    char s1[101];
    char s2[101];
    int dp[101][101]; //存s1[i]和s2[j]结尾的的公共子序列的长度
    while(scanf("%s %s",s1+1,s2+1) != EOF){ //从下标为1开始存
        int n = strlen(s1+1); //C字符数组长度用strlen()
        int m = strlen(s2+1);
        for(int i = 0; i <= n; ++i){
            for(int j = 0;j <= m; ++j){
                if(i==0 || j==0){
                    dp[i][j] = 0;
                    continue;
                }
                if(s1[i] == s2[j]){
                    dp[i][j] = dp[i-1][j-1] + 1; 
                }else{
                    dp[i][j] = max(dp[i-1][j],dp[i][j-1]);
                }
            }
        }
        printf("%d\n",dp[n][m]);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员爱德华

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值