2024年1月31日练习答案

P505 【基础】寻找祖先

给出充足的父子关系,请你编写程序找到某个人的最早的祖先。

规定每个人的名字都没有空格,且没有任意两个人的名字相同。最多可能有1000组父子关系,总人数最多可能达到50000人,家谱中的记载不超过30代。

分析
使用map<string,string> 建立父子关系
通过 u = p[u] 的方式查询 u 的父亲 p[u]

点击查看代码
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=1e3+10;
map<string,string> p;

string find(string s) {
    if(s!=p[s]) p[s]=find(p[s]);
    return p[s];
}
int main() {
    string s, father, child;
    while(cin>>s) {
        if(s=="$") break;
        if(s[0]=='#') {
            father = s.substr(1);
            if(!p.count(father)) p[father] = father;
        } else if(s[0]=='+') {
            child = s.substr(1);
            p[child] = father;
        } else if(s[0]=='?') {
            s.erase(0,1);
            cout<<s<<" "<<find(s)<<endl;
        }
    }
    return 0;
}

P541 【基础】吃西瓜( watermelon )

炎热的夏天来的可真快,小花猫和编程兔决定去买一个又大又甜的西瓜。可是小花和编程兔是两只非常奇怪的动物,都是偶数的爱好者,它们希望把西瓜切成两半后,每一部分的重量都是2的倍数公斤(大于 0)。

当然有编程兔在,它们很快就决定了买哪个瓜。小朋友你知道要不要买这个瓜吗?

分析
n是偶数,n/2是偶数,且n/2>1
也就是说 n = 2(a+b),a≥1,b≥1
所以 n/2 = (a+b) ≥ 2

点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=10;

int main(){
    int t,n; cin>>t;
    while(t--){
        cin>>n;
        int a = n/2;
        cout<<(n%2==0 && n/2>=2 ? "YES":"NO")<<endl;
    } 
    return 0;
}

P832 【提高】AtoB

给定一个 a进制数 c,将它变成 b进制并输出。

分析
模拟,一个比较好的代码量练习,想清楚过程,注意细节

点击查看代码
#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long LL;
const int N = 1e6 + 10;

string AtoB(string c, int a, int b) {
    LL t = 0;
    for (int i = 0; i < c.size(); i++) {
        if (c[i] <= '9') t = t * a + c[i] - '0';
        else t = t * a + c[i] - 'a' + 10;
    }
    string s;
    if (t == 0) s = "0";
    while (t) {
        LL r = t % b;
        if (r < 10) s.append(1, r + '0');
        else s.append(1, r - 10 + 'a');
        t /= b;
    }
    reverse(s.begin(), s.end());
    s = "(" + s + ")" + to_string(b);
    return s;
}
int main() {
    LL a, b; string c;
    cin >> c >> a >> b;
    cout << AtoB(c, a, b) << endl;
    return 0;
}

P841 【入门】s01串

s01串初始为"0",按以下方式变换:

  • 0变1
  • 1变01

求n次变换后s01串

分析
可以使用递归解决

  1. 递归函数:f(s) --- 表示返回经过1次变换的字符串
  2. 递归关系:f(s) = f(s的前一半) + f(s的后一半)
  3. 递归边界:f("0")="1", f("1")="01".
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=300;
int n;
string s = "0";
string f(string s) {
    if(s=="0") return "1";
    if(s=="1") return "01";
    int n = s.size(), k=n/2;
    return f(s.substr(0, k)) + f(s.substr(k));
}
int main() {
    cin>>n;
    while(n--) s = f(s);
    cout<<s;
    return 0;
}

P952 【入门】算24点

给出 n 组4个整数,请问有多少组整数,在不改变顺序,且不加入括号的情况下,可以通过+ - *三种运算,得到24。

比如1 2 3 4四个数,可以通过如下的方法得到24:123*4=24。

而20 30 40 50四个数,在不改变顺序、不添加括号的情况下,通过+ - *三种运算是无法获得24的。

分析
可以提前预处理出来所有的操作符,入:+++, +--, +-+ ...
再循环所有的操作符,看是否有满足24点的情况

点击查看代码
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=1e6+10;
string path[30], op="+-*";
int n,a[10],ans,p;

// dfs(m,s) : 将要新增第m个字符,且目前的操作符为 s.
void dfs(int m, string s) {
    if(m>3) {
        path[++p] = s;
        return;
    }
    for(int i=0; i<3; i++) {
        dfs(m+1, s+op.substr(i,1));
    }
}

int st[10];
int cal(string s) {
    int h=0, res=0;
    st[++h] = a[1];
    for(int i=0; i<3; i++) {
        if(s[i]=='+') st[++h] = a[i+2];
        if(s[i]=='-') st[++h] = -a[i+2];
        if(s[i]=='*') {
            int t = st[h--];
            st[++h] = t * a[i+2];
        }
    }
    while(h) res += st[h--];
    return res;
}
int main() {
    dfs(1, "");
    cin>>n;
    while(n--) {
        int f=0;
        for(int i=1; i<=4; i++)  cin>>a[i];
        string s;
        for(int i=1; i<=p; i++) {
            s = path[i];
//            for(int j=1; j<=4; j++) {
//                printf("%d", a[j]);
//                if(j<4) printf("%c", s[j-1]);
//            }
//            printf(" = %d\n", cal(s));
            if(cal(s)==24) { ans++; break; }
        }
    }
    printf("%d\n", ans);
    return 0;
}
posted @ 2024-01-30 21:10  HelloHeBin  阅读(86)  评论(0编辑  收藏  举报