【题解】入门篇(1)——入门模拟


前言

针对晴问算法网站第三章的题目所做的题解


3. 入门篇(1)——入门模拟

3.1简单模拟

3.1.1:3N+1猜想

思路:使n==1作为while循环的结束条件;while循环内用if语句对n进行奇偶判断 ,再执行相应的操作;奇偶判断方法:n%2;

#include <iostream>
using namespace std;

int main(){
    int n, steps = 0;
    cin>>n;
    while(n!=1){
        if(n%2==0)
            n = n/2;
        else
            n=(3*n+1)/2;
        steps++;
    }
    cout<<steps;
    return 0;
}

3.1.2:判断三角形

思路:使用if语句+逻辑与运算执行题目中的三个条件;

#include <iostream>
using namespace std;

int main(){
    int A, B, C;
    cin>>A>>B>>C;
    if(A+B>C && A+C>B && B+C>A)
        cout<<"YES";
    else
        cout<<"NO";
    return 0;
}

3.1.3:单调递增序列

思路:使用变量n和vector v接受输入的数据;设置标志flag=1,for循环遍历vector,如果发现一例前者大于后者的情况,则flag置位0;

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

int main(){
    int n, a;
    bool flag = 1;
    vector<int> v;
    cin>>n;
    for(int i = 0;i < n-1;i++){
        cin>>a;
        v.push_back(a);
    }
    for(int i = 0;i < v.size()-1;i++){
        if(v[i]>v[i+1])
            flag = 0;
    }
    if(flag)
        cout<<"YES";
    else
        cout<<"NO";
    return 0;
}

3.1.4:数列奇数和

思路:for循环遍历输入的数据,并进行奇偶判断,若为奇数则相加;

#include <iostream>
using namespace std;

int main(){
    int n, a, sum = 0;
    cin>>n;
    for(int i = 0;i < n;i++){
        cin>>a;
        if(a%2!=0)
            sum+=a;
    }
    cout<<sum;
    return 0;
}

3.1.5:三位数

思路:将整数作为字符串输入,for循环遍历字符串;‘n’ - ‘0’ == n;

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

int main(){
    string n;
    cin>>n;
    for(int i = 0;i < n.length();i++){
        cout<<n[i] - '0';
        if(i+1 != n.length())
            cout<<" ";
    }
    return 0;
}

3.1.6:水仙花数

思路:将整数作为字符串输入,for循环遍历字符串;‘n’ - ‘0’ == n;求幂pow(base,index);字符串转整数stoi(string);

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

int main(){
    string n;
    int sum = 0;
    cin>>n;
    for(int i = 0;i < n.length();i++){
        sum+=pow(n[i] - '0',3);
    }
    if(stoi(n) == sum)
        cout<<"YES";
    else
        cout<<"NO";
    return 0;
}

3.1.7:水仙花数II

思路:for循环遍历区间[a,b]内的所有数,将符合水仙花数的放入vector v中,若vector为空则输出NO,否则输出各个元素;

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

int main(){
    string a, b;
    vector<int> v;
    cin>>a>>b;
    for(int i = stoi(a);i < stoi(b)+1;i++){
        int sum = 0;
        for(int j = 0;j < 3;j++){
            sum+=pow(to_string(i)[j] - '0',3);
        }
        if(i == sum)
            v.push_back(i);
    }
    if(v.size() != 0){
        for(int i = 0;i < v.size();i++){
            cout<<v[i];
            if(i+1 != v.size())
                cout<<" ";
        }
    }
    else
        cout<<"NO";
    return 0;
}

3.1.8:2的幂

思路:输入参数为指数且最高为128,由于2^128数量很大,超出了类型表示的范围,故不能先求幂再求余,应根据公式(a * b)%1007 = ((a%1007) * (b%1007))%1007化简为(2 * 2 * 2…)%1007 = ((2%1007) * (2%1007) * …)%1007计算

#include <iostream>
using namespace std;

int main(){
    int n, result = 2;
    cin>>n;
    for(int i = 0;i < n-1;i++){
        result = (result%1007)*2;
    }
    cout<<result%1007;
    return 0;
}

3.2查找元素

3.2.1:查找元素

思路:将输入序列放入vector v中,for循环遍历查找;

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

int main(){
    int n, a, x, index, flag = false;
    vector<int> v;
    cin>>n;
    for(int i = 0;i < n;i++){
        cin>>a;
        v.push_back(a);
    }
    cin>>x;
    for(int i = 0;i < v.size();i++){
        if(v[i] == x){
            flag = true;
            index = i+1;
            break;
        }
    }
    if(flag)
        cout<<index;
    else
        cout<<"NO";
    return 0;
}

3.2.2:统计元素个数

思路:将输入序列放入vector v中,for循环遍历查找,计算出现次数;

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

int main(){
    int n, a, x, count = 0;
    vector<int> v;
    cin>>n;
    for(int i = 0;i < n;i++){
        cin>>a;
        v.push_back(a);
    }
    cin>>x;
    for(int i = 0;i < v.size();i++){
        if(v[i] == x)
            count++;
    }
    cout<<count;
    return 0;
}

3.2.3:寻找元素对

思路:将输入序列放入vector v中,两层for循环遍历,其中内层索引 j 只访问外层 索引i 之后的元素,避免重复计算次数;

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

int main(){
    int n, a, x, count = 0;
    vector<int> v;
    cin>>n;
    for(int i = 0;i < n;i++){
        cin>>a;
        v.push_back(a);
    }
    cin>>x;
    for(int i = 0;i < v.size()-1;i++){
        for(int j = i+1;j < v.size();j++){
            if(v[i]+v[j]==x)
                count++;
        }
    }
    cout<<count;
    return 0;
}

3.3图形输出

3.3.1:等腰直角三角形

思路:两层for循环,外层 i 为行数,内层 j 为列数;根据要求可知每行的列数 j 均不超过当前行数 i ,所以内层for循环的条件应为 j <= i ;

#include <iostream>
using namespace std;

int main(){
    int n;
    cin>>n;
    for(int i = 0;i < n;i++){
        for(int j = 0;j <= i;j++){
            cout<<"*";
        }
        cout<<endl;
    }
    return 0;
}

3.3.2:等腰直角三角形II

思路:空心三角形的输出可分为三部分,首行输出一个 * ,尾行行输出n个 * ,中间的n-2行使用两层for循环来处理,重点在于在内层for循环用if条件语句判断 i 与 j 的关系,决定是输出 * 还是空格;

#include <iostream>
using namespace std;

int main(){
    int n;
    cin>>n;
    cout<<"*"<<endl;
    for(int i = 0;i < n-2;i++){
        cout<<"*";
        for(int j = 0;j <= i;j++){
            if(j==i)
                cout<<"*";
            else
                cout<<" ";
        }
        cout<<endl;
    }
    for(int i = 0;i < n;i++){
        cout<<"*";
    }
    return 0;
}

3.3.3:画X

思路:对于两层for循环来说,循环次数若都为n的话输出为一个矩形,而题目要求每行最后一个 * 后为换行,* 前 非X位置为空格,所以需要在for循环内部加if条件语句控制输出内容;a和b为两个递增和递减的索引,控制是否输出 * ;flag标志含义为在每行是否已输出两个 * ,决定是否结束本行,进入下一行;X的中点由 a==n/2控制;

#include <iostream>
using namespace std;

int main(){
    int n;
    cin>>n;
    int a = 0, b = n-1, flag = 0;
    for(int i = 0;i < n;i++){
        for(int j = 0;j < n;j++){
            if(a == j || b == j){
                cout<<"*";
                flag++;
                if(a == n/2 || flag == 2)
                    break;
            }
            else
                cout<<" ";
        }
        flag = 0;
        a++;
        b--;
        cout<<endl;
    }
    return 0;
}

3.4日期处理

3.4.1:判断闰年

思路:判断闰年的方法:如果年份是400的倍数,或者是4的倍数但不是100的倍数,那么称这个年份为闰年;

#include <iostream>
using namespace std;

bool isLeapYear(int year){
    return (year%400 == 0)||(year%4 == 0 && year%100 != 0);
}

int main(){
    int n;
    cin>>n;
    if(isLeapYear(n))
        cout<<"YES";
    else
        cout<<"NO";
    return 0;
}

3.4.2:日期加法

思路:输入的天数n作为for循环的次数,每循环一次在日期上增加一天,在循环内部用if条件语句做好month和year的判断处理;

#include <cstdio>
using namespace std;

struct Date{
    int year, month, day;
};

int days[2][13] = {
    {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
    {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};

bool isLeapYear(int year){
    return (year%400 == 0)||(year%4 == 0 && year%100 != 0);
}

void addDays(Date &date, int n){
    for(int i = 0;i < n;i++){
        date.day++;
        if(date.day-1 == days[isLeapYear(date.year)][date.month]){
            date.day = 1;
            date.month++;
            if(date.month-1 == 12){
                date.month = 1;
                date.year++;
            }
        }
    }
}

int main(){
    Date date;
    int n;
    scanf("%d-%d-%d",&date.year ,&date.month ,&date.day);
    scanf("%d",&n);
    addDays(date, n);
    printf("%04d-%02d-%02d",date.year ,date.month ,date.day);
    return 0;
}

3.4.3:日期减法

思路:输入的天数n作为for循环的次数,每循环一次在日期上减去一天,在循环内部用if条件语句做好month和year的判断处理;

#include <cstdio>
using namespace std;

struct Date{
    int year, month, day;
};

int days[2][13] = {
    {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
    {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};

bool isLeapYear(int year){
    return (year%400 == 0)||(year%4 == 0 && year%100 != 0);
}

void subDays(Date &date, int n){
    for(int i = 0;i < n;i++){
        date.day--;
        if(date.day == 0){
            date.month--;
            if(date.month == 0){
                date.month = 12;
                date.year--;
            }
            date.day = days[isLeapYear(date.year)][date.month];
        }
    }
}

int main(){
    Date date;
    int n;
    scanf("%d-%d-%d",&date.year ,&date.month ,&date.day);
    scanf("%d",&n);
    subDays(date, n);
    printf("%04d-%02d-%02d",date.year ,date.month ,date.day);
    return 0;
}

3.4.4:一年中的第几天

思路:将日期分为三部分处理,对year的处理主要是判断是平年还是闰年;month作为for循环的判断条件,将1~month-1的天数加起来;最后再加上day就可以了;

#include <cstdio>
using namespace std;

struct Date{
    int year, month, day;
};

int days[2][13] = {
    {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
    {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};

bool isLeapYear(int year){
    return (year%400 == 0)||(year%4 == 0 && year%100 != 0);
}

int main(){
    Date date;
    int sum = 0;
    scanf("%d-%d-%d",&date.year ,&date.month ,&date.day);
    for(int i = 1;i < date.month;i++){
        sum += days[isLeapYear(date.year)][i];
    }
    printf("%d",sum+date.day);
    return 0;
}

3.4.5:日期先后

思路:按照year,month,day的顺序判断日期先后;

#include <cstdio>
using namespace std;

struct Date{
    int year, month, day;
};

int days[2][13] = {
    {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
    {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};

bool isLeapYear(int year){
    return (year%400 == 0)||(year%4 == 0 && year%100 != 0);
}

bool isBefore(Date date1, Date date2){
    if(date1.year != date2.year)
        return date1.year < date2.year;
    if(date1.month != date2.month)
        return date1.month < date2.month;
    return date1.day < date2.day;
}

int main(){
    Date date1;
    Date date2;
    scanf("%d-%d-%d",&date1.year ,&date1.month ,&date1.day);
    scanf("%d-%d-%d",&date2.year ,&date2.month ,&date2.day);
    if(isBefore(date1, date2))
        printf("YES");
    else
        printf("NO");
    return 0;
}

3.4.6:周几

思路:计算输入的日期与函数内一个定好的日期(周日)的天数差;对7取余输出;x%7 的值只可能为0-6;

#include <cstdio>
using namespace std;

struct Date{
    int year, month, day;
};

int days[2][13] = {
    {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
    {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};

bool isLeapYear(int year){
    return (year%400 == 0)||(year%4 == 0 && year%100 != 0);
}

bool isBefore(Date date1, Date date2){
    if(date1.year != date2.year)
        return date1.year < date2.year;
    if(date1.month != date2.month)
        return date1.month < date2.month;
    return date1.day < date2.day;
}

int dayDiffer(Date date1, Date date2){
    int steps = 0;
    while(isBefore(date1, date2)){
        date1.day++;
        if(date1.day-1 == days[isLeapYear(date1.year)][date1.month]){
            date1.day = 1;
            date1.month++;
            if(date1.month-1 == 12){
                date1.month = 1;
                date1.year++;
            }
        }
        steps++;
    }
    return steps;
}

int main(){
    Date date_comp = {2022,06,26};
    Date date;
    int differ = 0;
    scanf("%d-%d-%d",&date.year ,&date.month ,&date.day);
    if(isBefore(date,date_comp))
        printf("%d",dayDiffer(date, date_comp)%7?7-(dayDiffer(date, date_comp)%7):dayDiffer(date, date_comp)%7);
    else
        printf("%d",dayDiffer(date_comp, date)%7);
    return 0;
}

3.5进制转换

3.5.1:十进制转二进制

思路:除基取余法;用do while循环的原因是:对入口参数特殊值0的处理;

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

int main(){
    int n;
    vector<int> v;
    cin>>n;
    do{
        v.push_back(n%2);
        n/=2;
    }while(n!=0);
    for(int i = v.size()-1;i > -1;i--)
        cout<<v[i];
    return 0;
}

3.5.2:二进制转十进制

思路:取出输入参数的每一位,并乘上对应的2^(n-1),相加即可

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

int main(){
    string n;
    int dec = 0, index = 1;
    cin>>n;
    for(int i = n.size()-1;i > -1;i--){
        dec += (n[i]-'0')*index;
        index *= 2;
    }
    cout<<dec;
    return 0;
}

3.5.3:十进制转K进制

思路:除基取余法;用do while循环的原因是:对入口参数特殊值0的处理;考虑到16进制的情况,把10-15换成A-F输出;

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

int main(){
    int n, k;
    vector<int> v;
    cin>>n>>k;
    do{
        v.push_back(n%k);
        n/=k;
    }while(n!=0);
    for(int i = v.size()-1;i > -1;i--){
        if(v[i]>9)
            cout.put(v[i]-10+'A');
        else
            cout<<v[i];
    }
    return 0;
}

3.5.4:K进制转十进制

思路:取出输入参数的每一位,并乘上对应的k^(n-1),相加即可;考虑到16进制的情况,把A-F换成10-15计算;

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

int main(){
    string n;
    int k;
    int dec = 0, index = 1;
    cin>>n>>k;
    for(int i = n.size()-1;i > -1;i--){
        if(n[i]-55>9)
            dec += (n[i]-55)*index;
        else
            dec += (n[i]-'0')*index;
        index *= k;
    }
    cout<<dec;
    return 0;
}

3.6字符串处理

3.6.1:回文串

思路:for循环遍历一半的字符串,控制索引比较首尾;i和s.length()-1-i;

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

int main(){
    string s;
    bool flag = true;
    cin>>s;
    for(int i = 0;i < s.length()/2;i++){
        if(s[i] != s[s.length()-1-i])
            flag = 0;
    }
    if(flag)
        cout<<"YES";
    else
        cout<<"NO";
    return 0;
}

3.6.2:单词倒序

思路:将单词按输入顺序存入vector v中,for循环倒序遍历输出;

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

int main(){
    string s;
    vector<string> v;
    while(cin>>s)
        v.push_back(s);
    for(int i = 0;i < v.size();i++){
        cout<<v[v.size()-1-i];
        if(i+1 != v.size())
            cout<<" ";
    }
    return 0;
}

3.6.3:单词倒序II

思路:将单词按输入顺序存入vector v中,使用双重for循环遍历输出,外层for循环选定单词,内层for循环将单词倒序;

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

int main(){
    string s;
    vector<string> v;
    while(cin>>s)
        v.push_back(s);
    for(int i = 0;i < v.size();i++){
        for(int j = 0;j < v[i].length();j++){
            cout<<v[i][v[i].length()-1-j];
        }
        if(i+1 != v.size())
            cout<<" ";
    }
    return 0;
}

3.6.4:单词数

思路:设置一个变量count初始值为0作为计数器,将cin>>s放入while()循环作为条件,当没有单词输入时,会跳出循环;

#include <iostream>
using namespace std;

int main(){
    string s;
    int count = 0;
    while(cin>>s)
        count++;
    cout<<count;
    return 0;
}

3.6.5:首字母大写

思路:将单词按输入顺序存入vector v中,使用for循环遍历每个单词,访问首字母完成替换;

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

int main(){

    string s;
    vector<string> v;
    while(cin>>s)
        v.push_back(s);
    for(int i = 0;i < v.size();i++){
        v[i][0] = v[i][0] + ('A'-'a');
        cout<<v[i];
        if(i+1 != v.size())
            cout<<" ";
    }
    return 0;
}

3.6.6:公共前缀

思路:将输入的字符串依次存入vector v中,并且统计出最小的长度(min_length);双重for循环遍历v,外层决定遍历字符串,内层决定遍历字符串的字符,且内层次数由min_length决定;以第一个字符串为基,与后续字符串依次比较,得出最短的公共长度(common_length),输出第一个字符串common_length长度的字符;

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

int main(){
    string s;
    int n, min_length = 51, common_length = 51;
    vector<string> v;
    cin>>n;
    for(int i = 0;i < n;i++){
        cin>>s;
        if(s.length()<min_length)
            min_length = s.length();
        v.push_back(s);
    }
    for(int i = 1;i < v.size();i++){
        int temp = 0;
        for(int j = 0;j < min_length;j++){
            if(v[0][j] == v[i][j])
                temp++;
            else
                break;
        }
        if(temp < common_length)
            common_length = temp;
    }
    for(int i = 0;i < common_length;i++)
        cout<<v[0][i];
    return 0;
}

3.6.7:连续相同字符统计

思路:for循环遍历输入的字符串,前后字符相同则count++,字符不同则count重新计数,并输出上一个字符的数据;

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

int main(){
    string s;
    int count = 0;
    cin>>s;
    for(int i = 0;i < s.length();i++){
        count++;
        if(s[i]!=s[i+1]){
            cout<<s[i]<<" "<<count;
            if(i+1 != s.length())
                cout<<endl;
            count = 0;
        }
    }
    return 0;
}

3.6.8:C语言合法变量名

思路:for循环遍历输入的字符串,根据变量名的规则写出if条件语句判断即可;

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

int main(){
    string s;
    bool flag = true;
    cin>>s;
    for(int i = 0;i < s.length();i++){
        if(i){
            if(('A'<=s[i]&&s[i]<='Z')||('a'<=s[i]&&s[i]<='z')||(s[i]-'0'<=9&&s[i]-'0'>=0)||s[i]=='_')
                flag = true;
            else{
                flag = false;
                break;
            }
        }
        else{
            if(s[i]-'0'<=9 && s[i]-'0'>=0){
                flag = false;
                break;
            }
        }
    }
    if(flag)
        cout<<"YES";
    else
        cout<<"NO";
    return 0;
}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值