2020牛客暑期多校训练营(第七场)A、B、C、D、H、J题解及补题

2020牛客暑期多校训练营(第七场)题解及补题

比赛过程

这场打出了牛客排名新低,原因一来这场题目难度差别较大,我们前期思考的有点慢也wa了很多发罚时炸了,二来读题能力确实不太行,J题读了一小时多才读懂,已经没是没时间写了。

题解

A

题意

给一个半径为 r r r的圆,在圆内找到 n n n个整数点,求 ∑ i = 1 n − 1 ∑ j = i + 1 n d i s t ( i , j ) 2 \sum_{i=1}^{n-1}\sum_{j=i+1}^{n}dist(i,j)^2 i=1n1j=i+1ndist(i,j)2的最大值,其中 d i s t ( i , j ) dist(i,j) dist(i,j)指点 i i i与点 j j j之间的欧几里得距离。

解法

通过拆分计算 ∑ i = 1 n − 1 ∑ j = i + 1 n d i s t ( i , j ) 2 = n ∑ i = 1 n ( x i 2 + y i 2 ) − ( ∑ i = 1 n x i ) 2 − ( ∑ i = 1 n y i ) 2 \sum_{i=1}^{n-1}\sum_{j=i+1}^{n}dist(i,j)^2=n\sum_{i=1}^{n}(x_{i}^2+y_{i}^2)-(\sum_{i=1}^{n}x_{i})^2-(\sum_{i=1}^{n}y_{i})^2 i=1n1j=i+1ndist(i,j)2=ni=1n(xi2+yi2)(i=1nxi)2(i=1nyi)2,维护一个 d p [ i ] [ j ] [ k ] dp[i][j][k] dp[i][j][k]表示前 i i i个点横坐标和为 j j j,纵坐标和为 k k k每个点到圆心距离的平方和的最大值,根据 d p [ i ] [ j ] [ k ] dp[i][j][k] dp[i][j][k]更新 a n s [ i ] [ r ] ans[i][r] ans[i][r] a n s [ i ] [ r ] = m a x ( i ∗ d p [ i ] [ j ] [ k ] − j 2 − k 2 ) ans[i][r]=max(i\ast dp[i][j][k]-j^2-k^2) ans[i][r]=max(idp[i][j][k]j2k2)

代码
#pragma GCC optimize("O3")
#pragma G++ optimize("O3")

#include <bits/stdc++.h>
//#include <ext/pb_ds/assoc_container.hpp>
//#include <ext/pb_ds/tree_policy.hpp>
//#include <ext/pb_ds/priority_queue.hpp>

//using namespace __gnu_pbds;
using namespace std;

#define ll long long
#define ld long double
#define ull unsigned long long
#define mst(a, b) memset((a), (b), sizeof(a))
#define mp(a, b) make_pair(a, b)
#define pi acos(-1)
#define endl '\n'
#define pii pair<int, int>
#define pll pair<ll, ll>
#define pdd pair<double, double>
#define vi vector<int>
#define vl vector<ll>
#define pb push_back
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
#define lowbit(x) x &(-x)
#define all(x) (x).begin(), (x).end()
#define sf(x) scanf("%d", &x)
#define pf(x) printf("%d\n", x)
#define debug(x) cout << x << endl
#define mod(x) (x % mod + mod) % mod

template <typename T>
void read(T &x) {
    x = 0;
    char ch = getchar();
    ll f = 1;
    while (!isdigit(ch)) {
        if (ch == '-')
            f *= -1;
        ch = getchar();
    }
    while (isdigit(ch)) {
        x = x * 10 + ch - 48;
        ch = getchar();
    }
    x *= f;
}

const int INF = 0x3f3f3f3f;
const ll inf = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-8;
const int maxn = 3e3 + 7;
const int maxm = 1e5 + 7;
const int mod = 1e9 + 7;

#define IO ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
//template<typename T> using ordered_set = tree<T,null_type,less<T>,rb_tree_tag,tree_order_statistics_node_update>;
struct node {
    int r, x, y;
} q[maxn];
bool cmp(node a, node b) {
    return a.r < b.r;
}
int dp[10][606][606], ans[10][35], tot = 0;
void init() {
    for (int i = -30; i <= 30; ++i)
        for (int j = -30; j <= 30; ++j)
            if (i * i + j * j <= 900)
                q[++tot] = {i * i + j * j, i, j};
    sort(q + 1, q + 1 + tot, cmp);
    mst(dp, -INF);
    int cnt = 1;
    dp[0][300][300] = 0;
    for (int r = 1; r <= 30; ++r) {
        for (; cnt <= tot && q[cnt].r <= r * r; ++cnt) {
            node res = q[cnt];
            for (int i = 1; i <= 8; ++i)
                for (int j = -r * i + 300; j <= r * i + 300; ++j)
                    for (int k = -r * i + 300; k <= r * i + 300; ++k)
                        dp[i][j][k] = max(dp[i][j][k], dp[i - 1][j - res.x][k - res.y] + res.r);
        }
        for (int i = 1; i <= 8; ++i)
            for (int j = -r * i; j <= r * i; ++j)
                for (int k = -r * i; k <= r * i; ++k)
                    ans[i][r] = max(ans[i][r], i * max(dp[i][j + 300][k + 300], 0) - j * j - k * k);
    }
}
int main() {
    IO;
    init();
    int t;
    cin >> t;
    while (t--) {
        int n, r;
        cin >> n >> r;
        cout << ans[n][r] << endl;
    }
    return 0;
}

B

题意

n ⋅ m n \cdot m nm个口罩,装最少的箱,使得在个数平均的情况下,既能分箱分给 n n n 个医院,也能分给 m m m 个医院。

解法

通过画图可知,有一个 n ⋅ m n \cdot m nm 的矩形,这个矩形可以是立着的也可以是躺着的,那么可以不断的填充最大的正方形,因为正方形是旋转 90 90 90 度不变的,所以可以将这个矩形不断填充最大的正方形,进而转换为子问题.过程类似gcd.

代码
#include <stdio.h>

#include <algorithm>
#include <cmath>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <vector>
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 111;
const ll mod = 1e9 + 7;
#define P pair<int, int>
vector<int> ans;
void solve(int x, int y) {
    if (x == 0 || y == 0) return;
    if (x < y) swap(x, y);
    x -= y;
    for (int i = 1; i <= y; ++i) ans.push_back(y);
    solve(x, y);
}
int main() {
    int T;
    scanf("%d", &T);
    while (T--) {
        ans.clear();
        int n, m;
        scanf("%d%d", &n, &m);
        solve(n, m);
        int rr = ans.size();
        printf("%d\n", rr);
        for (int i = 0; i < rr; ++i) {
            printf("%d%c", ans[i], i < rr - 1 ? ' ' : '\n');
        }
    }
    return 0;
}

C

题意

有一棵树,三种操作:
∙ \bullet 选定一个中心城市 x x x ,其他所有城市的值加 w − d i s t ( x , y ) w-dist(x,y) wdist(x,y)
∙ \bullet 将城市 x x x 的值与 0 0 0 取min
∙ \bullet 询问单点的值

解法

首先,操作2可以记录一个 d e l t a delta delta 数组,判断当前的值并进行改变。
对于操作1,可以发现
w − d i s t ( x , y ) = w − d e p [ x ] − d e p [ y ] + 2 ⋅ d e p [ l c a ( x , y ) ] w-dist(x,y)=w-dep[x]-dep[y]+2\cdot dep[lca(x,y)] wdist(x,y)=wdep[x]dep[y]+2dep[lca(x,y)]
那么我们可以维护一个全局变量 s u m sum sum ,操作次数为 c n t t cntt cntt,每次进行1操作, sum+=w-dep[x]。这样前三项都维护好了,那么怎么计算 d e p [ l c a ( x , y ) ] dep[lca(x,y)] dep[lca(x,y)] 呢。
显然 l c a ( x , y ) lca(x,y) lca(x,y) 一定在 x , y x,y x,y 的上方,那么对于每一次操作1,都把从 x x x 到根节点的值+1,那么 d e p [ l c a ( x , y ) ] dep[lca(x,y)] dep[lca(x,y)] 的值就等于从 y y y 到根节点所有的值相加,使用轻重链剖分来维护即可。
那么对某一个点 y y y 的询问, v a l [ y ] = s u m − c n t t ⋅ d e p [ y ] + 2 ∗ q u e r y ( 1 , y ) val[y]=sum-cntt \cdot dep[y]+2*query(1,y) val[y]=sumcnttdep[y]+2query(1,y)

代码
#pragma region
#include <algorithm>
#include <cmath>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
using namespace std;
typedef long long ll;
#define tr t[root]
#define lson t[root << 1]
#define rson t[root << 1 | 1]
#define rep(i, a, n) for (ll i = a; i <= n; ++i)
#define per(i, a, n) for (ll i = n; i >= a; --i)
namespace fastIO {
#define BUF_SIZE 100000
#define OUT_SIZE 100000
//fread->R
bool IOerror = 0;
//inline char nc(){char ch=getchar();if(ch==-1)IOerror=1;return ch;}
inline char nc() {
    static char buf[BUF_SIZE], *p1 = buf + BUF_SIZE, *pend = buf + BUF_SIZE;
    if (p1 == pend) {
        p1 = buf;
        pend = buf + fread(buf, 1, BUF_SIZE, stdin);
        if (pend == p1) {
            IOerror = 1;
            return -1;
        }
    }
    return *p1++;
}
inline bool blank(char ch) { return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t'; }
template <class T>
inline bool R(T &x) {
    bool sign = 0;
    char ch = nc();
    x = 0;
    for (; blank(ch); ch = nc())
        ;
    if (IOerror)
        return false;
    if (ch == '-')
        sign = 1, ch = nc();
    for (; ch >= '0' && ch <= '9'; ch = nc())
        x = x * 10 + ch - '0';
    if (sign)
        x = -x;
    return true;
}
inline bool R(double &x) {
    bool sign = 0;
    char ch = nc();
    x = 0;
    for (; blank(ch); ch = nc())
        ;
    if (IOerror)
        return false;
    if (ch == '-')
        sign = 1, ch = nc();
    for (; ch >= '0' && ch <= '9'; ch = nc())
        x = x * 10 + ch - '0';
    if (ch == '.') {
        double tmp = 1;
        ch = nc();
        for (; ch >= '0' && ch <= '9'; ch = nc())
            tmp /= 10.0, x += tmp * (ch - '0');
    }
    if (sign)
        x = -x;
    return true;
}
inline bool R(char *s) {
    char ch = nc();
    for (; blank(ch); ch = nc())
        ;
    if (IOerror)
        return false;
    for (; !blank(ch) && !IOerror; ch = nc())
        *s++ = ch;
    *s = 0;
    return true;
}
inline bool R(char &c) {
    c = nc();
    if (IOerror) {
        c = -1;
        return false;
    }
    return true;
}
template <class T, class... U>
bool R(T &h, U &... t) { return R(h) && R(t...); }
#undef OUT_SIZE
#undef BUF_SIZE
};  // namespace fastIO
using namespace fastIO;
template <class T>
void _W(const T &x) { cout << x; }
void _W(const int &x) { printf("%d", x); }
void _W(const int64_t &x) { printf("%lld", x); }
void _W(const double &x) { printf("%.16f", x); }
void _W(const char &x) { putchar(x); }
void _W(const char *x) { printf("%s", x); }
template <class T, class U>
void _W(const pair<T, U> &x) { _W(x.F), putchar(' '), _W(x.S); }
template <class T>
void _W(const vector<T> &x) {
    for (auto i = x.begin(); i != x.end(); _W(*i++))
        if (i != x.cbegin()) putchar(' ');
}
void W() {}
template <class T, class... U>
void W(const T &head, const U &... tail) { _W(head), putchar(sizeof...(tail) ? ' ' : '\n'), W(tail...); }
#pragma endregion
const int maxn = 5e4 + 5;
int n, m;
vector<int> g[maxn];
int fa[maxn], sz[maxn], dep[maxn], son[maxn];
int id[maxn], cnt, top[maxn];
int delta[maxn], sum, cntt;
void init() {
    rep(i, 1, n) {
        g[i].clear();
        cntt = sum = delta[i] = 0;
        son[i] = fa[i] = sz[i] = dep[i] = 0;
        cnt = 0;
        top[i] = 0;
    }
}
void dfs1(int u, int f, int deep) {
    dep[u] = deep, fa[u] = f, sz[u] = 1;
    for (auto v : g[u]) {
        if (v == f) continue;
        dfs1(v, u, deep + 1);
        sz[u] += sz[v];
        if (sz[v] > sz[son[u]]) son[u] = v;
    }
}
void dfs2(int u, int topf) {
    id[u] = ++cnt;
    top[u] = topf;
    if (!son[u]) return;
    dfs2(son[u], topf);
    for (auto v : g[u]) {
        if (v == fa[u] || v == son[u]) continue;
        dfs2(v, v);
    }
}
struct segtree {
    int l, r, val, lazy;
} t[maxn << 2];
void build(int root, int l, int r) {
    tr.l = l, tr.r = r, tr.lazy = 0, tr.val = 0;
    if (l == r) return;
    int mid = (l + r) >> 1;
    build(root << 1, l, mid);
    build(root << 1 | 1, mid + 1, r);
    tr.val = lson.val + rson.val;
}
void spread(int root) {
    if (tr.lazy) {
        lson.val += tr.lazy * (lson.r - lson.l + 1);
        rson.val += tr.lazy * (rson.r - rson.l + 1);
        lson.lazy += tr.lazy;
        rson.lazy += tr.lazy;
        tr.lazy = 0;
    }
}
int query(int root, int l, int r) {
    if (l <= tr.l && tr.r <= r) return tr.val;
    spread(root);
    int ans = 0;
    int mid = (tr.l + tr.r) >> 1;
    if (l <= mid) ans += query(root << 1, l, r);
    if (r > mid) ans += query(root << 1 | 1, l, r);
    return ans;
}
void update(int root, int l, int r, int x) {
    if (l <= tr.l && tr.r <= r) {
        tr.val += x * (tr.r - tr.l + 1);
        tr.lazy += x;
        return;
    }
    spread(root);
    int mid = (tr.l + tr.r) >> 1;
    if (l <= mid) update(root << 1, l, r, x);
    if (r > mid) update(root << 1 | 1, l, r, x);
    tr.val = lson.val + rson.val;
}
void updRange(int x, int y, int k) {
    while (top[x] != top[y]) {
        if (dep[top[x]] < dep[top[y]]) swap(x, y);
        update(1, id[top[x]], id[x], k);
        x = fa[top[x]];
    }
    if (dep[x] > dep[y]) swap(x, y);
    update(1, id[x], id[y], k);
}
int qRange(int x, int y) {
    int ans = 0;
    while (top[x] != top[y]) {
        if (dep[top[x]] < dep[top[y]]) swap(x, y);
        ans += query(1, id[top[x]], id[x]);
        x = fa[top[x]];
    }
    if (dep[x] > dep[y]) swap(x, y);
    ans += query(1, id[x], id[y]);
    return ans;
}
int solve(int x) {
    return sum - cntt * dep[x] + 2 * qRange(1, x);
}
int main() {
    int T;
    R(T);
    while (T--) {
        R(n, m);
        init();
        rep(i, 1, n - 1) {
            int u, v;
            R(u, v);
            g[u].push_back(v);
            g[v].push_back(u);
        }
        dfs1(1, 0, 1);
        dfs2(1, 1);
        build(1, 1, n);
        while (m--) {
            int op, x, w;
            R(op);
            if (op == 1) {
                R(x, w);
                sum += w - dep[x];
                cntt++;
                updRange(1, x, 1);
            } else if (op == 2) {
                R(x);
                ll tmp = solve(x) + delta[x];
                if (tmp > 0) delta[x] -= tmp;
            } else {
                R(x);
                W(solve(x) + delta[x]);
            }
        }
    }
}

D

题意

给一个 n n n ($1\le n \le 10^{15} $),判断 ∑ k = 1 n k 2 \sum_{k=1}^{n} k^2 k=1nk2是不是一个平方数.

解法

打表可知只有 n = 1 n=1 n=1 n = 24 n=24 n=24 时结果是一个平方数.

代码
#include <stdio.h>

#include <algorithm>
#include <cmath>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <vector>
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 111;
const int mod = 1e9 + 7;
#define P pair<int, int>
int main() {
    int T;
    scanf("%d", &T);
    while (T--) {
        ll n;
        scanf("%lld", &n);
        if (n == 1 || n == 24) {
            puts("Fake news!");
        } else {
            puts("Nobody knows it better than me!");
        }
    }
    return 0;
}

E

题意
解法
代码

F

题意
解法
代码

G

题意
解法
代码

H

题意

∙ \bullet (1,k) 是一个Legend Tuple
∙ \bullet 如果 (n,k) 是一个Legend Tuple,那么(n+k,k) 和 (n ⋅ \cdot k,k)也是一个Legend Tuple.
求在范围 1 ≤ n ≤ N 1 \le n \le N 1nN , 1 ≤ k ≤ K 1 \le k \le K 1kK 的范围内有多少组(n,k)是Legend Tuple.

解法

∙ \bullet 首先 (1,k) 是一个Legend Tuple
∙ \bullet 那么当 n % k = = 1 n\%k==1 n%k==1 时,由加法运算可知(n,k)是一个Legend Tuple.
∙ \bullet 由乘法运算可知, (k,k)是一个Legend Tuple,再由加法运算可知当 $n%k==0 $ 时, (n,k)是一个Legend Tuple.

如果 (n,k) 是一个Legend Tuple
如果只使用加法运算,那么满足 n % k = = 1 n\%k==1 n%k==1,如果使用了乘法运算,那么一定有 n % k = = 0 n\%k==0 n%k==0 ,前面已经证明当 n n n k k k 的倍数时,(n,k)是一个Legend Tuple.
所以,(n,k)是一个Legend Tuple的充要条件为 n % k = = 0 ∣ ∣ n % k = = 1 n\%k==0||n\%k==1 n%k==0n%k==1.

对于每一个 k ( k ≥ 2 ) k(k\ge 2) k(k2) , n n n 可取 1 , k , k + 1 , 2 ⋅ k , … 1,k,k+1,2 \cdot k,\dots 1,k,k+1,2k, ,也就是 $ 2\cdot \left \lfloor \frac{N}{k} \right \rfloor + (N%k!=0)$.
显然当 k = 1 k=1 k=1 时有 n n n 组.
综上,答案为 ∑ k = 1 K { 2 ⋅ ⌊ N k ⌋ + ( N % k ! = 0 ) } \sum_{k=1}^{K} \left \{ 2\cdot \left \lfloor \frac{N}{k} \right \rfloor + (N\%k!=0)\right \} k=1K{2kN+(N%k!=0)},前面部分使用除法分块,后面部分筛一下 N N N 的因子即可.
注意乘法会暴longlong ,需要使用快速乘.

代码
#pragma region
#include <algorithm>
#include <cmath>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
using namespace std;
typedef long long ll;
#define rep(i, a, n) for (ll i = a; i <= n; ++i)
#define per(i, a, n) for (ll i = n; i >= a; --i)
namespace fastIO {
#define BUF_SIZE 100000
#define OUT_SIZE 100000
//fread->R
bool IOerror = 0;
//inline char nc(){char ch=getchar();if(ch==-1)IOerror=1;return ch;}
inline char nc() {
    static char buf[BUF_SIZE], *p1 = buf + BUF_SIZE, *pend = buf + BUF_SIZE;
    if (p1 == pend) {
        p1 = buf;
        pend = buf + fread(buf, 1, BUF_SIZE, stdin);
        if (pend == p1) {
            IOerror = 1;
            return -1;
        }
    }
    return *p1++;
}
inline bool blank(char ch) { return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t'; }
template <class T>
inline bool R(T &x) {
    bool sign = 0;
    char ch = nc();
    x = 0;
    for (; blank(ch); ch = nc())
        ;
    if (IOerror)
        return false;
    if (ch == '-')
        sign = 1, ch = nc();
    for (; ch >= '0' && ch <= '9'; ch = nc())
        x = x * 10 + ch - '0';
    if (sign)
        x = -x;
    return true;
}
inline bool R(double &x) {
    bool sign = 0;
    char ch = nc();
    x = 0;
    for (; blank(ch); ch = nc())
        ;
    if (IOerror)
        return false;
    if (ch == '-')
        sign = 1, ch = nc();
    for (; ch >= '0' && ch <= '9'; ch = nc())
        x = x * 10 + ch - '0';
    if (ch == '.') {
        double tmp = 1;
        ch = nc();
        for (; ch >= '0' && ch <= '9'; ch = nc())
            tmp /= 10.0, x += tmp * (ch - '0');
    }
    if (sign)
        x = -x;
    return true;
}
inline bool R(char *s) {
    char ch = nc();
    for (; blank(ch); ch = nc())
        ;
    if (IOerror)
        return false;
    for (; !blank(ch) && !IOerror; ch = nc())
        *s++ = ch;
    *s = 0;
    return true;
}
inline bool R(char &c) {
    c = nc();
    if (IOerror) {
        c = -1;
        return false;
    }
    return true;
}
template <class T, class... U>
bool R(T &h, U &... t) { return R(h) && R(t...); }
#undef OUT_SIZE
#undef BUF_SIZE
};  // namespace fastIO
using namespace fastIO;
template <class T>
void _W(const T &x) { cout << x; }
void _W(const int &x) { printf("%d", x); }
void _W(const int64_t &x) { printf("%lld", x); }
void _W(const double &x) { printf("%.16f", x); }
void _W(const char &x) { putchar(x); }
void _W(const char *x) { printf("%s", x); }
template <class T, class U>
void _W(const pair<T, U> &x) { _W(x.F), putchar(' '), _W(x.S); }
template <class T>
void _W(const vector<T> &x) {
    for (auto i = x.begin(); i != x.end(); _W(*i++))
        if (i != x.cbegin()) putchar(' ');
}
void W() {}
template <class T, class... U>
void W(const T &head, const U &... tail) { _W(head), putchar(sizeof...(tail) ? ' ' : '\n'), W(tail...); }
#pragma endregion
const ll mod = 1e9 + 7;
ll mul(ll a, ll b) {
    ll ans = 0;
    while (b) {
        if (b & 1) ans = (ans + a) % mod;
        a = (a + a) % mod;
        b >>= 1;
    }
    return ans;
}
int main() {
    ll n, k;
    R(n, k);
    ll ans = 0;
    for (ll l = 1, r; l <= k; l = r + 1) {
        r = (n / l ? min(k, n / (n / l)) : k);
        ans = (ans + mul(n / l, r - l + 1)) % mod;
    }
    ans = (ans + ans - n + mod) % mod;  //对1的修正
    ans = (ans + k) % mod;
    for (ll i = 1; i * i <= n; ++i) {
        if (n % i == 0) {
            if (i <= k) --ans;
            if (i * i != n && n / i <= k) --ans;
        }
    }
    W((ans + mod) % mod);
}

I

题意
解法
代码

J

题意

一个程序内有四种语句,且程序对语句顺序不敏感(可能以任意顺序执行),问每个指针最后可能指向的对象集合。

解法

读题题,读完题类似建图的直接模拟就行。

代码
#include <stdio.h>

#include <algorithm>
#include <cmath>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <vector>
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 111;
const ll mod = 1e9 + 7;
#define P pair<int, int>
char s[300][200];
int tmp[30][30][30], G[30][30];
int n;
void solve() {
    for (int i = 1; i <= n; ++i) {
        if (s[i][1] == '.') {  // 3
            char a = s[i][0], b = s[i][6];
            for (int j = 0; j < 26; ++j) {
                if (G[a - 'A'][j]) {
                    for (int k = 0; k < 26; ++k) {
                        if (G[b - 'A'][k]) tmp[j][s[i][2] - 'a'][k] = 1;
                    }
                }
            }
        } else if (s[i][5] == '.') {  // 4
            char a = s[i][0], b = s[i][4];
            for (int j = 0; j < 26; ++j) {
                if (G[b - 'A'][j]) {
                    for (int k = 0; k < 26; ++k) {
                        if (tmp[j][s[i][6] - 'a'][k]) {
                            G[s[i][0] - 'A'][k] = 1;
                        }
                    }
                }
            }

        } else if (s[i][4] >= 'a' && s[i][4] <= 'z') {  // 1
            char a = s[i][0], b = s[i][4];
            G[a - 'A'][b - 'a'] = 1;

        } else {  // 2
            char a = s[i][0], b = s[i][4];
            for (int j = 0; j < 26; ++j) {
                if (G[b - 'A'][j]) {
                    G[a - 'A'][j] = 1;
                }
            }
        }
    }
}
int main() {
    scanf("%d", &n);
    getchar();
    for (int i = 1; i <= n; ++i) {
        gets(s[i]);
    }
    solve();
    int last = -1;
    for (int i = 1; i <= 55; ++i) solve();
    for (int i = 0; i < 26; ++i) {
        printf("%c: ", 'A' + i);
        for (int j = 0; j < 26; ++j) {
            if (G[i][j]) printf("%c", j + 'a');
        }
        puts("");
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值