天梯赛 训练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; }