天梯赛 训练round 3

7-9 特立独行的幸福 (25 分)

题意:

一个数进行各个位上的数字求平方和 得到下一个数 一直这样操作 直到最后等于1 那么就称这个数为幸福数 但是要满足没有其他数经过它然后最终变成1 求一个范围内的独立幸福数

思路:

遍历这个范围内的数迭代 这个数 每次用vector储存由他迭代而来的数 且标记 这些数为非独立数 如果遇到循环就说明这个数不是独立幸福树跳出循环 当迭代结果是1时就停止循环然后标记这个数是独立的 再记录它的附和数的个数 即vector的大小 用map记录 最后只要再遍历一遍范围 将是独立幸福数的信息输出即可

因为数据并不大 只要模拟就好 想复杂了反而容易错

#include <bits/stdc++.h> 
#include <cstdlib>
#include <cmath>
#define ll long long
using namespace std;
const int N = 1e5 + 10;
int n, m, cnt, a[1010], ndl[N], vis[N];

bool isprime(int x){//判断素数
    if(x <= 1) return false;
    for(int i = 2; i * i <= x; i++){
        if(x % i == 0) return false;
    }
    return true;
}
vector<int>v;
map<int, int> mp;
int sp(int x){//各位数平方
    int ans = 0;
    while(x > 0){
        ans += (x % 10) * (x % 10);
        x /= 10;
    }
    return ans;
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin >> n >> m;
    for(int i = n; i <= m; i++){
        vector<int> v;
        int x = i;
        while(x != 1){
            int s = sp(x), ff = 1;
            x = s;
            for(int j = 0; j < v.size(); j++){
                if(s == v[j]){//遇到循环 
                    //ndl[s] = 1;
                    //ndl[i] = 1; 
                    ff = 0;
                    break;
                } 
            }
            if(!ff) break;
            v.push_back(s);
            ndl[s] = 1;
        }
        if(x == 1) mp[i] = v.size();//是幸福数 记录它的附和数个数
        
    }
    int flag = 0;
    for(int i = n; i <= m; i++){ 
        //一定要加上!mp[i]因为前面当遇到循环时 没有将s 和i标记为非独立幸福数 (而如果有前面的注释部分可以不用!mp[i])
        if(ndl[i] || !mp[i]) continue;
        if(isprime(i)) cout << i << " " << mp[i] * 2 << "\n";
        else cout << i << " " << mp[i] << "\n";
        flag = 1;
    }
    if(!flag) cout << "SAD\n";
       return 0;
}

 

7-10 冰岛人 (25 分)

题意:

一个人的名字有名 和 姓组成 如果是普京人 那么儿子的姓是父亲的名+sson 女儿的姓是父亲的名+sdottir 不是普京人 男人姓后面加m 女人姓后面加f 

给n个人名 和 姓 再q次询问 给出两个人的名和姓 没有后缀 如果其中有一个不存在输出“NA" 如果为同性别 输出 ”Whatever“ 其余判断两人5代以内是否有同一个祖先(五代内没有共同祖先的要求是 两人的共同祖先比任何一方的曾祖父大)

思路:

这题主要要灵活运用map和 string 然后注意判断五代以内共同祖先的方法 具体看代码及注释

我这最后一个测试点超时了 之后再优化吧

 

#include <iostream>
#include <map>
#include <cstdio>
#include <string>
#include <vector>
#include <queue>
#include <algorithm>
#define ll long long
#define pi acos(-1)
#define FF ios::sync_with_stdio(false), cin.tie(0)
using namespace std;
const int mod = 1e9 + 7;
const int N = 1e6 + 10;
const int inf = 0x3f3f3f3f;
int  n, k;
string s;
map<string, string>fa;
map<string, int>sx;

bool judge(string a, string b) {//判断5代内是否有共同祖先 共同祖先可能不是同一辈的
    int i = 1, j;
    for (string xx = a; sx[xx]; i++) {
        j = 1;
        for (string yy = b; sx[yy]; j++) {    //循环结束的条件是后面已经没有人了sx可以标记该人是否存在
            if (i > 4 && j > 4)    //5代以外了直接跳出循环 标记真
                return true;
            if (xx == yy && (i <= 4 || j <= 4))    //5代以内 公共祖先比至少一方的曾曾祖父小
                return false;
            yy = fa[yy];
        }
        xx = fa[xx];
    }
    return true;    
}
//这个不对不符合祖先比任何一方的曾祖父大 而要求了比两方都大
/*bool judge(string a, string b) {
    string xx = a, yy;
    for (int i = 1; i < 5; i++) {
        yy = b;
        for (int j = 1; j < 5; j++) {
            if (xx == yy) return false;
            if (yy.empty())
                break;
            yy = fa[yy];
        }
        if (xx.empty())
            break;
        xx = fa[xx];
    }
    return true;
}*/

void solve() {
    cin >> n;
    string x, y;
    for (int i = 1; i <= n; i++) {
        cin >> x >> y;//可以直接这样输入 应为cin会跳过空白符 
        if (y.back() == 'n') {//s.back()获取s的最后一个字符
            fa[x] = y.substr(0, y.size() - 4);//用substr()函数获取姓 
            sx[x] = 1;//记录性别
        }
        else if (y.back() == 'r') {
            fa[x] = y.substr(0, y.size() - 7);
            sx[x] = 2;
        }
        else if (y.back() == 'm') {
            sx[x] = 1;
        }
        else sx[x] = 2;
    }
    int q;
    cin >> q;
    string a, s1, b, s2;
    for (int i = 1; i <= q; i++) {
        cin >> a >> s1 >> b >> s2;//可以这样写 cin会跳过空白符 s1 s2主要就是储存输入对后面没影响
        if (!sx[a] || !sx[b]) {//有一方不存在
            cout << "NA\n";
        }
        else if (sx[a] == sx[b]) {//同性别
            cout << "Whatever\n";
        }
        else {//判断是否再5带内有共同祖先
            if (judge(a, b)) cout << "Yes\n";
            else cout << "No\n";
        }
    }
}

int main()
{
    FF;
    solve();
    return 0;
}

 

 

 

7-12 彩虹瓶 (25 分)

题意:

几种颜色按顺序填 每次去搬来一种颜色 是当前要填的就填下 不是就暂时叠放到临时架子上 存放的物品不能超过架子的容量m 按先后顺序叠放 后续也按从上到下取 如果要取的物品上还有物品也无法顺利填好颜色 求是否能顺利填好颜色

思路:

利用栈简单模拟就好了 就是要注意多个测试例子 每次要把栈清空 stack 没有clear()

#include <bits/stdc++.h> 
#include <cstdlib>
#define ll long long
using namespace std;
const int N = 1e5 + 10;
int ans[500];
vector<int> g[N];
int n, m, k, a[1010];
queue<int>q;
stack<int>st;

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n, yy;
    cin >> n >> m >> k;
    while(k --){
        while(!st.empty()) st.pop();//清空数据
        for(int i = 1; i <= n; i++){
            cin >> a[i];
        }
        int pre = 1, flag = 1;//pre代表当前要填颜色的编号
        for(int i = 1; i <= n; i++){
            if(a[i] != pre) {//不符合先放到临时架子上
                st.push(a[i]);
                if(st.size() > m){//临时架子满出了就不符合
                    flag = 0;
                    break;
                }
            }
            else pre++;//可以填颜色 pre就指向下一个颜色
            while(!st.empty()){//再去看看临时架子上的颜色有没有可填的
                int xx = st.top();
                if(xx != pre) break;
                while(xx == pre) {
                    st.pop();
                    pre++;
                    if(st.empty()) break;
                    xx = st.top();
                }
            }
            
        }
        //如果栈不为空说明 不能顺利填颜色
        if(flag && st.empty()) cout << "YES\n";
        else cout << "NO\n";
    }
       return 0;
}

 

posted @ 2022-03-12 09:46  Yaqu  阅读(59)  评论(0)    收藏  举报