2019GPLT

2019GPLT

7-2 6翻了

从左到右扫描输入的句子:如果句子中有超过 3 个连续的 6,则将这串连续的 6 替换成 9;但如果有超过 9 个连续的 6,则将这串连续的 6 替换成 27。其他内容不受影响,原样输出。

题解:模拟

救命了,这么水的模拟题都过不了

#include <bits/stdc++.h>

using namespace std;
int main()
{
    int i = 0, l, j, cnt = 0;
    string s;
    getline(cin, s);
    l = s.length();
    while (i < l)
    {
        if (s[i] != '6')
            cout << s[i++];
        else
        {
            for (cnt = 0; i < l && s[i] == '6'; i++, cnt++)
                ;
            if (cnt > 9)
                cout << 27;
            else if (cnt > 3)
                cout << 9;
            else
                while (cnt-- > 0)
                    cout << 6;
        }
    }
    return 0;
}

7-3 敲笨钟

对每一行诗句,判断其是否压“ong”韵。即上下两句末尾的字都是“ong”结尾。如果是压此韵的,就按题面方法糟改之后输出,输出格式同输入;否则输出 Skipped,即跳过此句。

题解:

利用\(find\)函数即可



#include <bits/stdc++.h>
#define Zeoy std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0)
#define debug(x) cerr << #x << '=' << x << endl
#define all(x) (x).begin(), (x).end()
#define rson id << 1 | 1
#define lson id << 1
#define int long long
#define mpk make_pair
#define endl '\n'
using namespace std;
typedef unsigned long long ULL;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-9;
const int N = 1e5 + 10, M = 4e5 + 10;

string s;
string cmp = "qiao ben zhong.";

void solve()
{
    int cnt = 0;
    getline(cin, s);
    if (s.find("ong,") != -1 && s.find("ong.") != -1)
    {
        int pos = -1;
        for (int i = 1; i <= 2; ++i)
        {
            pos = s.rfind(" ");
            s.erase(pos);
        }
        pos = s.rfind(" ");
        for (int i = 0; i <= pos; ++i)
            cout << s[i];
        cout << cmp << endl;
    }
    else
        cout << "Skipped" << endl;
}
signed main(void)
{
    Zeoy;
    int T = 1;
    cin >> T;
    cin.ignore();
    while (T--)
    {
        solve();
    }
    return 0;
}

7-9 特立独行的幸福

对一个十进制数的各位数字做一次平方和,称作一次迭代。如果一个十进制数能通过若干次迭代得到 1,就称该数为幸福数。1 是一个幸福数。此外,例如 19 经过 1 次迭代得到 82,2 次迭代后得到 68,3 次迭代后得到 100,最后得到 1。则 19 就是幸福数。显然,在一个幸福数迭代到 1 的过程中经过的数字都是幸福数,它们的幸福是依附于初始数字的。例如 82、68、100 的幸福是依附于 19 的。而一个特立独行的幸福数,是在一个有限的区间内不依附于任何其它数字的;其独立性就是依附于它的的幸福数的个数。如果这个数还是个素数,则其独立性加倍。例如 19 在区间[1, 100] 内就是一个特立独行的幸福数,其独立性为 2×4=8。

另一方面,如果一个大于1的数字经过数次迭代后进入了死循环,那这个数就不幸福。例如 29 迭代得到 85、89、145、42、20、4、16、37、58、89、…… 可见 89 到 58 形成了死循环,所以 29 就不幸福。

本题就要求你编写程序,列出给定区间内的所有特立独行的幸福数和它的独立性。

\(1<A<B≤10^4\)

题解:记忆化搜索\(DFS\)

在回溯的时候将不是依附的幸福数标记即可,同时我们需要一个数组在回溯的时候记录依附于该幸福数的数



#include <bits/stdc++.h>
#define Zeoy std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0)
#define debug(x) cerr << #x << '=' << x << endl
#define all(x) (x).begin(), (x).end()
#define rson id << 1 | 1
#define lson id << 1
#define int long long
#define mpk make_pair
#define endl '\n'
using namespace std;
typedef unsigned long long ULL;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-9;
const int N = 2e5 + 10, M = 4e5 + 10;

int l, r;
int vis[N];
int pre[N];

bool isprime(int x)
{
    if (x < 2)
        return false;
    for (int i = 2; i <= x / i; ++i)
    {
        if (x % i == 0)
            return false;
    }
    return true;
}

map<int, bool> mp;

bool dfs(int x)
{
    if (pre[x] > 0)
        return true;
    if (x == 1)
        return true;
    if (vis[x])
        return false;
    vis[x] = 1;
    int t = x;
    int y = 0;
    while (t)
    {
        y += (t % 10) * (t % 10);
        t /= 10;
    }
    bool f = dfs(y);
    if (f)
    {
        mp[y] = false;
        pre[x] = y;
    }
    vis[x] = 0;
    return f;
}

void solve()
{
    pre[1] = 0;
    cin >> l >> r;
    for (int i = l; i <= r; ++i)
    {
        if (mp.count(i) == 0)
        {
            if (!dfs(i))
                mp[i] = false;
            else
                mp[i] = true;
        }
    }

    int flag = false;
    for (int i = l; i <= r; ++i)
    {
        if (mp[i] == true)
        {
            flag = true;
            int cnt = 0;
            int p = pre[i];
            while (p != 0)
            {
                cnt++;
                p = pre[p];
            }
            if (isprime(i))
                cout << i << " " << 2 * cnt << endl;
            else
                cout << i << " " << cnt << endl;
        }
    }
    if (!flag)
        cout << "SAD" << endl;
}
signed main(void)
{
    Zeoy;
    int T = 1;
    // cin >> T;
    while (T--)
    {
        solve();
    }
    return 0;
}

7-10 冰岛人

冰岛人沿用的是维京人古老的父系姓制,孩子的姓等于父亲的名加后缀,如果是儿子就加 sson,女儿则加 sdottir。因为冰岛人口较少,为避免近亲繁衍,本地人交往前先用个 App 查一下两人祖宗若干代有无联系。本题就请你实现这个 App 的功能。

对每一个查询,根据结果在一行内显示以下信息:

  • 若两人为异性,且五代以内无公共祖先,则输出 Yes
  • 若两人为异性,但五代以内(不包括第五代)有公共祖先,则输出 No
  • 若两人为同性,则输出 Whatever
  • 若有一人不在名单内,则输出 NA

题解:模拟

根据题意模拟即可,但是需要注意以下几点:

  1. 只要有一人在五代以内的祖先和另一个异性的祖先是一样的,就说明有公共祖先
  2. 如果超过五代依旧没有出现公共祖先,那就不用再找了,说明五代以内没有公共祖先
  3. 对于不是本地人,我们实际上不需要去记录它的姓名,如果记录了,我们反而会在检查本地人时出现错误,因为很有可能是同名的
#include <bits/stdc++.h>
#define Zeoy std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0)
#define debug(x) cerr << #x << '=' << x << endl
#define all(x) (x).begin(), (x).end()
#define rson id << 1 | 1
#define lson id << 1
#define int long long
#define mpk make_pair
#define endl '\n'
using namespace std;
typedef unsigned long long ULL;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-9;
const int N = 1e5 + 10, M = 4e5 + 10;

map<string, int> mp;
int n, q;

struct node
{
    int sex; // 0 man, 1 woman
    string name;
} a[N];

bool check(string x, string y)
{
    int i = 1;
    for (string s1 = x; !s1.empty(); ++i)
    {
        int j = 1;
        for (string s2 = y; !s2.empty(); ++j)
        {
            if (i >= 5 && j >= 5)
                break;
            if (s1 == s2 && (i < 5 || j < 5))
                return false;
            s2 = a[mp[s2]].name;
        }
        s1 = a[mp[s1]].name;
    }
    return true;
}

void solve()
{
    cin >> n;
    int cnt = 0;
    for (int i = 1; i <= n; ++i)
    {
        string t, s;
        cin >> t >> s;
        mp[t] = i;
        if (s.back() == 'm')
            a[i].sex = 0;
        else if (s.back() == 'f')
            a[i].sex = 1;
        else if (s.back() == 'n')
        {
            a[i].sex = 0;
            int cnt = 4;
            while (cnt--)
                s.erase(s.end() - 1);
            a[i].name = s;
        }
        else if (s.back() == 'r')
        {
            a[i].sex = 1;
            int cnt = 7;
            while (cnt--)
                s.erase(s.end() - 1);
            a[i].name = s;
        }
    }
    cin >> q;
    while (q--)
    {
        string t1, s1, t2, s2;
        cin >> t1 >> s1 >> t2 >> s2;
        if (!mp[t1] || !mp[t2])
            cout << "NA" << endl;
        else if (a[mp[t1]].sex == a[mp[t2]].sex)
            cout << "Whatever" << endl;
        else
        {
            if (check(t1, t2))
                cout << "Yes" << endl;
            else
                cout << "No" << endl;
        }
    }
}
signed main(void)
{
    Zeoy;
    int T = 1;
    // cin >> T;
    while (T--)
    {
        solve();
    }
    return 0;
}

7-13 地铁一日游

森森喜欢坐地铁。这个假期,他终于来到了传说中的地铁之城——魔都,打算好好过一把坐地铁的瘾!

魔都地铁的计价规则是:起步价 2 元,出发站与到达站的最短距离(即计费距离)每 K 公里增加 1 元车费。

例如取 K = 10,动安寺站离魔都绿桥站为 40 公里,则车费为 2 + 4 = 6 元。

为了获得最大的满足感,森森决定用以下的方式坐地铁:在某一站上车(不妨设为地铁站 A),则对于所有车费相同的到达站,森森只会在计费距离最远的站或线路末端站点出站,然后用森森美图 App 在站点外拍一张认证照,再按同样的方式前往下一个站点。

坐着坐着,森森突然好奇起来:在给定出发站的情况下(在出发时森森也会拍一张照),他的整个旅程中能够留下哪些站点的认证照?

地铁是铁路运输的一种形式,指在地下运行为主的城市轨道交通系统。一般来说,地铁由若干个站点组成,并有多条不同的线路双向行驶,可类比公交车,当两条或更多条线路经过同一个站点时,可进行换乘,更换自己所乘坐的线路。举例来说,魔都 1 号线和 2 号线都经过人民广场站,则乘坐 1 号线到达人民广场时就可以换乘到 2 号线前往 2 号线的各个站点。换乘不需出站(也拍不到认证照),因此森森乘坐地铁时换乘不受限制。

N 个车站 (1 ≤ N ≤ 200),M 条线路 (1 ≤ M ≤ 1500)

题解:Floyd + DFS

首先本题很明显要用到两点之间的最短路,并且n<200,说明我们可以使用\(floyd\)求出任意两个站点之间的距离,那么接下来我们对他会出站拍照的情况进行分析:

  1. 当前站点是端点站,所以我们需要记录每个站点是否是端点站
  2. 当前站点是某个费用下可以到达的最远的车站

所以我们可以先枚举每个站点作为起点,将其每种花费下的最远的站记录下来,也就是说如果u作为起点,那么他只会到达它每种花费下最远的站和端点站,这样的话我们就可以建图了,现在图上两点之间的边都是互相可达的

然后我们在面对查询时,我们只需要对图进行dfs即可,就能求出以u为起点所能到达的所有点,然后将这些点进行排序,输出即可

下面有个重点需要注意以下:

我们如何对每种花费记录最远的站是哪个站,实际上我们只需要利用map记录每种花费的最远距离,然后再遍历一遍所有点到u的距离是不是最远的即可,因为很有可能花费一样,路程也是一样最远的有好几个点,我们不要漏掉了

其次对于不连通的两个站点,我们没有必要再去计算,不然我们加入计算的话,那最大距离不就是无穷大了嘛,显然不对

#include <bits/stdc++.h>
#define Zeoy std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0)
#define debug(x) cerr << #x << '=' << x << endl
#define all(x) (x).begin(), (x).end()
#define rson id << 1 | 1
#define lson id << 1
#define int long long
#define mpk make_pair
#define endl '\n'
using namespace std;
typedef unsigned long long ULL;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-9;
const int N = 2e2 + 10, M = 4e5 + 10;

int n, m, k, q;
vector<int> g[N];
int f[N][N];
bool isEnd[N];
bool vis[N];
set<int> st;

void dfs(int u)
{
    for (auto v : g[u])
    {
        if (!vis[v])
        {
            st.insert(v);
            vis[v] = true;
            dfs(v);
        }
    }
}

void solve()
{
    cin >> n >> m >> k;
    for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= n; ++j)
        {
            f[i][j] = INF;
            f[i][i] = 0;
        }
    for (int i = 1; i <= m; ++i)
    {
        int pre = -1;
        int cnt = 0;
        int dis, u;
        do
        {
            cnt++;
            if (cnt % 2 == 0)
                cin >> dis;
            else
            {
                cin >> u;
                if (pre == -1)
                {
                    isEnd[u] = true;
                    pre = u;
                    continue;
                }
                f[u][pre] = min(f[u][pre], dis);
                f[pre][u] = min(f[pre][u], dis);
                pre = u;
            }
        } while (cin.get() != '\n');
        isEnd[u] = true;
    }
    for (int k = 1; k <= n; ++k)
        for (int u = 1; u <= n; ++u)
            for (int v = 1; v <= n; ++v)
                f[u][v] = min(f[u][v], f[u][k] + f[k][v]);
    for (int i = 1; i <= n; ++i)
    {
        map<int, int> mp;
        for (int j = 1; j <= n; ++j)
            if (i != j && f[i][j] != INF)
                if (!mp[2 + f[i][j] / k] || f[i][j] > mp[2 + f[i][j] / k])
                    mp[2 + f[i][j] / k] = f[i][j];
        for (int j = 1; j <= n; ++j)
        {
            if (f[i][j] == INF)
                continue;
            if (f[i][j] == mp[2 + f[i][j] / k] || isEnd[j] == true)
                g[i].push_back(j);
        }
    }
    cin >> q;
    while (q--)
    {
        int s;
        cin >> s;
        memset(vis, 0, sizeof vis);
        st.clear();
        st.insert(s);
        dfs(s);
        for (auto it = st.begin(); it != st.end(); ++it)
        {
            if (it != st.begin())
                cout << " ";
            cout << *it;
        }
        cout << endl;
    }
}
signed main(void)
{
    Zeoy;
    int T = 1;
    // cin >> T;
    while (T--)
    {
        solve();
    }
    return 0;
}
posted @ 2023-03-09 20:39  Zeoy_kkk  阅读(52)  评论(0编辑  收藏  举报