ZISUOJ 高级语言程序设计实训-基础B(部分题)

说明:

        有几个题是不会讲的,我只能保证大家拿保底分。

题目列表:

问题 A: 统计字母个数

思路:

        把'a'到'z'放map里处理后输出即可。

参考题解:

#include <iostream>
#include <string>
#include <map>
using std::cin;
using std::cout;
int main() {
    cin.tie(nullptr)->sync_with_stdio(false);
    std::string s;
    std::map<char,int> mp;
    for(int i = 0;i<26;i++) mp['a'+i] = 0;
    while(cin >> s) {
        for(auto &c:s) if(c>='a'&&c<='z') mp[c]++;
        if(s[s.size()-1]=='#') break;
    }
    for(auto &i:mp) {
        cout << i.first << ' ' << i.second << '\n';
    }
    return 0;
}

问题 B: 小数化分数1

思路:

        以字符串形式读入小数,从第三个字符开始统计,分子初始化为0,分母初始化为1,分子每次乘以10再加上字符-'0'的值(或者直接异或48也能实现同样的效果),分母每次乘以10,把两个数都除以它们的最大公约数再输出即可。

参考题解:

#include <iostream>
#include <string>
#include <algorithm>
using std::cin;
using std::cout;
void solve() {
    std::string n;cin >> n;
    int fenzi = 0,fenmu = 1;
    for(int i = 2;i<n.size();i++) {
        fenzi = fenzi*10+(n[i]^48);
        fenmu *= 10;
    }
    int gcd = std::__gcd(fenzi,fenmu);
    cout << fenzi/gcd << '/' << fenmu/gcd << '\n';
}
int main() {
    cin.tie(nullptr)->sync_with_stdio(false);
    int T = 1;cin >> T;
    while(T--) {
        solve();
    }
    return 0;
}

问题 C: 筛排处理

思路:

        把数据都放进set里面,注意一下输出的格式即可。

参考题解:

#include <iostream>
#include <set>
using std::cin;
using std::cout;
void solve(int &n) {
    std::set<int> set;
    for(int i = 1;i<=n;i++) {
        int tmp;cin >> tmp;
        set.insert(tmp);
    }
    int count = 0;
    cout << set.size() << '\n';
    for(auto &i:set) {
        count++;
        cout << i << " \n"[count%10==0];
    }
    if(count%10!=0) cout << '\n';
}
int main() {
    cin.tie(nullptr)->sync_with_stdio(false);
    int n = 1;
    while(cin >> n) {
        if(n==0) {
            cout << "0\n";
            break;
        }
        solve(n);
        cout << '\n';
    }
    return 0;
}

问题 D: 产生冠军

思路:

        读入所有比赛结果,第一遍遍历时把每场比赛的胜者都放入winner候选人名单中(实际上就是丢进set中),第二遍遍历时把每场的败者从winner候选人名单中剔除,最后判断winner候选人名单的大小,如果size为1,则可以唯一确定winner,否则则不行。

参考题解:

#include <iostream>
#include <string>
#include <vector>
#include <set>
using std::cin;
using std::cout;
void solve(const int &n) {
    std::vector<std::pair<std::string,std::string>> competitions;
    std::set<std::string> set;
    for(int i = 0;i<n;i++) {
        std::string winner,loser;
        cin >> winner >> loser;
        competitions.emplace_back(winner,loser);
        set.insert(winner);
    }
    for(int i = 0;i<n;i++) {
        set.erase(competitions[i].second);
    }
    cout << (set.size()==1?"Yes\n":"No\n");
}
int main() {
    cin.tie(nullptr)->sync_with_stdio(false);
    int n = 1;
    while(cin >> n,n) {
        solve(n);
    }
    return 0;
}

问题 F: 恺撒密码

思路:

        基本的字符变换题,这里注意读入的问题即可。用C语言的gets()读入需要提前把上一行的换行符读掉,用C++的getline()读入时也要用cin.get()或者再用一个getline()把换行符读掉。

参考题解:

#include <iostream>
#include <string>
using std::cin;
using std::cout;
int main() {
    cin.tie(nullptr)->sync_with_stdio(false);
    int n = 1;cin >> n;
    // std::cin.get();
    std::string s,temps;
    getline(cin,temps);
    getline(cin,s);
    for(auto &c:s) {
        if(c>='a'&&c<='z') {
            cout << char('a'+(c-'a'+n)%26);
        }else cout << char(c);
    }
    cout << std::endl;
    return 0;
}

问题 G: 切割正方体

思路:

        考察思维,所有能切出的立方体都不大于长方体的长宽高的最大公约数,因此我们只需要计算长宽高的最大公约数的因子个数即可。

参考题解:

#include <iostream>
#include <algorithm>
#include <vector>
using std::cin;
using std::cout;
int main() {
    cin.tie(nullptr)->sync_with_stdio(false);
    int length,width,height;
    while(cin >> length >> width >> height,length||width||height) {
        int common_gcd = std::__gcd(std::__gcd(length,width),height);
        std::vector<int> factor;
        for(int i = 1;i<=common_gcd/i;i++) {
            if(common_gcd%i==0) {
                factor.emplace_back(i);
                if(i!=common_gcd/i) {
                    factor.emplace_back(common_gcd/i);
                }
            }
        }
        cout << factor.size() << '\n';
    }
    return 0;
}

问题 H: 核反应堆

思路:

        模拟一下每一秒发生的事情即可。注意此处可能会爆int,因此要开long long。

参考题解:

#include <iostream>
using ll = long long;
using std::cin;
using std::cout;
int main() {
    cin.tie(nullptr)->sync_with_stdio(false);
    int n = 1;
    while(cin >> n,n!=-1) {
        ll high=1,low=0;
        for(int i = 1;i<=n;i++) {
            ll temp_high = high,temp_low = low;
            high = temp_high*3+temp_low*2;
            low = temp_high+temp_low;
        }
        cout << high << ", " << low << '\n';
    }
    return 0;
}

问题 I: 天花板

思路:
        实现向上取整即可。直接用写好的函数(<cmath>头文件中的ceil()函数)即可。

参考题解:

#include <iostream>
#include <cmath>
using std::cin;
using std::cout;
int main() {
    cin.tie(nullptr)->sync_with_stdio(false);
    int n = 1;cin >> n;
    for(int i = 1;i<=n;i++) {
        double number;cin >> number;
        cout << std::ceil(number) << '\n';
    }
    return 0;
}

问题 K: 统计立方数

思路:

        打个表把unsigned int范围内的所有立方数都放进vector中,之后读入数据时去这个vector使用二分查找,如果找到了,则ans++,否则continue

参考题解:

#include <iostream>
#include <vector>
#include <algorithm>
#include <climits>
using ll = long long;
using std::cin;
using std::cout;
int main() {
    cin.tie(nullptr)->sync_with_stdio(false);
    std::vector<ll> cubes;
    for(ll i = 1;i*i*i<=UINT_MAX;i++) {
        cubes.emplace_back(i*i*i);
    }
    ll n,ans = 0;
    while(cin >> n,n) {
        if(std::binary_search(cubes.begin(),cubes.end(),n)) {
            ans++;
        }
    }
    cout << ans << std::endl;
    return 0;
}

问题 M: 剪花布条

思路:

        字串查找题,可以用暴力匹配、kmp算法等思路。我这里直接用<string>头文件的find()类函数实现的查找。

参考题解:

#include <iostream>
#include <string>
using std::cin;
using std::cout;
int main() {
    cin.tie(nullptr)->sync_with_stdio(false);
    std::string s,subs;
    while(cin >> s,s!="#") {
        cin >> subs;
        int index = 0,ans = 0;
        while(s.find(subs,index)!=std::string::npos) {
            index = s.find(subs,index)+subs.size();
            ans++;
        }
        cout << ans << '\n';
    }
    return 0;
}

问题 N: 不要62

思路:

        根据数据范围10^6,我直接使用最暴力的方法,遍历n到m,每个遍历到的数,都把它转成字符串,再使用<string>的find()函数来查找'4'和'62',如果找到了,count++,否则continue,最后输出m-n+1-count即可。

参考题解:

#include <iostream>
#include <string>
using std::cin;
using std::cout;
int main() {
    cin.tie(nullptr)->sync_with_stdio(false);
    int n,m;
    while(cin >> n >> m,n||m) {
        int count = 0;
        for(int i = n;i<=m;i++) {
            std::string s = std::to_string(i);
            if(s.find('4')!=std::string::npos||s.find("62")!=std::string::npos) {
                count++;
            }
        }
        cout << m-n+1-count << '\n';
    }
    return 0;
}

问题 O: 过原点的直线数

思路:

        要判断是否存在点与原点(0,0)的连线也经过了其他点,最简单的方式是求出所有点(xi,yi)的最大公约数,都放进set中去重输出set的大小即可。

参考题解:

#include <iostream>
#include <set>
#include <algorithm>
using std::cin;
using std::cout;
void solve() {
    int n;cin >> n;
    std::set<std::pair<int,int>> slopes;
    for(int i = 1;i<=n;i++) {
        int x,y;cin >> x >> y;
        int gcd = std::__gcd(x,y);
        slopes.insert(std::make_pair(x/gcd,y/gcd));
    }
    cout << slopes.size() << '\n';
}
int main() {
    cin.tie(nullptr)->sync_with_stdio(false);
    int T = 1;
    cin >> T;
    while(T--) {
        solve();
    }
    return 0;
}

问题 P: 数的计数

思路:

        很明显的dfs题,注意写的时候容易爆int,记得开long long。

参考题解:

#include <iostream>
#include <cstring>
using ll = long long;
using std::cin;
using std::cout;
void dfs(int u,ll *a) {
    if(a[u]!=-1) return;
    a[u] = 1;
    for(int i = 1;i<=u/2;i++) {
        dfs(i,a);
        a[u]+=a[i];
    }
}
int main() {
    cin.tie(nullptr)->sync_with_stdio(false);
    constexpr int N = 1e3+5;
    ll a[N];
    memset(a,-1,sizeof a);
    int n;cin >> n;
    dfs(n,a);
    cout << a[n] << std::endl;
    return 0;
}

问题 Q: 排列

思路:

        dfs入门最经典的题目,不过此题要注意输出的格式。我就不写dfs了,直接用STL的全排列函数了。

参考题解:

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using std::cin;
using std::cout;
int main() {
    cin.tie(nullptr)->sync_with_stdio(false);
    constexpr int N = 1e1+5;
    int n = 1;cin >> n;
    for(int i = 1;i<=n;i++) {
        int a[N];
        for(int j = 1;j<=4;j++) {
            cin >> a[j];
        }
        std::sort(a+1,a+1+4);
        std::vector<std::string> ans;
        do {
            std::string s;
            for(int i = 1;i<=4;i++) s = s+char(a[i]^48);
            ans.emplace_back(s);
        }while(std::next_permutation(a+1,a+1+4));
        for(int j = 0;j<ans.size();j++) {
            cout << ans[j] << " \n"[(j+1)%6==0];
        }
        if(i!=n) cout << '\n';
    }
    return 0;
}

问题 R: 排列2

思路:

        是上个题的hard版本,只需要注意全排列第一个元素为0时丢弃,其他情况都放进vector中,再排序去重,但是注意输出的格式。

参考题解:

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using std::cin;
using std::cout;
int main() {
    cin.tie(nullptr)->sync_with_stdio(false);
    int a,b,c,d;
    int num[5];
    while(cin >> a >> b >> c >> d,a||b||c||d) {
        num[1] = a,num[2] = b,num[3] = c,num[4] = d;
        std::sort(num+1,num+1+4);
        std::vector<std::string> ans;
        do {
            if(num[1]==0) continue;
            std::string s;
            for(int i = 1;i<=4;i++) {
                s = s + char(num[i]^48);
            }
            ans.emplace_back(s);
        }while(std::next_permutation(num+1,num+1+4));
        std::sort(ans.begin(),ans.end());
        char last = ans[0][0];
        for(int i = 0;i<ans.size();i++) {
            if(ans[i][0]!=last) {
                cout << '\n' << ans[i] << ' ';
                last = ans[i][0];
            }else {
                cout << ans[i] << ' ';
            }
        }
        cout << '\n' << '\n';
    }
    return 0;
}

问题 S: 最多拦截导弹数

思路:

        第一眼看到题,还以为是最经典的动态规划的最长上升子序列模型题,结果只是一个很傻的贪心题,直接写即可。

参考题解:

#include <iostream>
using std::cin;
using std::cout;
int main() {
    cin.tie(nullptr)->sync_with_stdio(false);
    constexpr int N = 1e3+5;
    int n;
    while(cin >> n,n) {
        int height[N];
        for(int i = 1;i<=n;i++) cin >> height[i];
        int now = 30000,ans = 0;
        for(int i = 1;i<=n;i++) {
            if(now>=height[i]) {
                now = height[i];
                ans++;
            }else break;
        }
        cout << ans << '\n';
    }
    return 0;
}

问题 T: 昊城的分割游戏

思路:

        题目看着很唬人,以为要用什么很复杂的数据结构或者算法思想,但是推几个样例就会发现答案不是0就是1,而且只跟读入数据对4取模的值有关。

参考题解:

#include <iostream>
using std::cin;
using std::cout;
int main() {
    cin.tie(nullptr)->sync_with_stdio(false);
    int n;cin >> n;
    cout << (n%4==1||n%4==2?1:0) << std::endl;
    return 0;
}

  • 30
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Beau_Will

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

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

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

打赏作者

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

抵扣说明:

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

余额充值