2020 HDU Multi-University Training Contest 6

2020 HDU Multi-University Training Contest 6

文章目录

      • 2020 HDU Multi-University Training Contest 6
    • @[toc]
          • 1001 Road To The 3rd Building
            • 思路
            • 代码
          • 1002 Little Rabbit's Equation
            • 思路
            • 代码
          • 1009 Divisibility
            • 思路
            • 代码
          • 1006 A Very Easy Graph Problem
            • 题意
            • 思路
            • 代码
          • 1010 Expectation
            • 题意
            • 思路
            • 代码
          • 1005 Fragrant numbers
            • 题意
            • 思路

1001 Road To The 3rd Building

链接:HDU6827 Road To The 3rd Building

思路
  • 线性求逆元,前缀和处理逆元
  • 分别计算每一位上对期望的贡献
代码
#include 
using namespace std;
#define int long long
const int MAXN = 2e5 + 7;;
const int MOD = 1e9 + 7;
// const int INF = ;
// const double eps = ;
// const int DIRX[] = {};
// const int DIRY[] = {};

inline int getpow(int a, int b)
{
    int ret = 1;
    for (; b; b >>= 1, a = a * a % MOD)
        if (b & 1)
            ret = ret * a % MOD;
    return ret;
}

int inv[MAXN];
int pre[MAXN];

void getinv()
{
    inv[1] = 1;
    for (int i = 2; i <= 2e5; ++i)
        inv[i] = (MOD - MOD / i) * inv[MOD % i] % MOD;
    pre[0] = 0;
    for(int i = 1;i <= 2e5; i++){
        pre[i] = (pre[i-1] + inv[i]) % MOD;
    }
}

int T;
int n;
int s[MAXN];
int sum;
int tot;
int val;
int ans;

int32_t main(void)
{
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    getinv();
    cin >> T;
    while (T--)
    {
        cin >> n;
        for (int i = 1; i <= n; ++i)
        {
            cin >> s[i];
            s[i] %= MOD;
        }
        sum = 0;
        tot = 0;
        for (int i = 1; 2 * i <= n; ++i)
        {
            tot += (pre[n - i + 1] - pre[i - 1] + MOD) % MOD;
            tot %= MOD;
            val = s[i] + s[n - i + 1] % MOD;
            sum += val * tot % MOD;
            sum %= MOD;
        }
        if (n % 2)
        {
            tot += inv[n / 2 + 1] % MOD;
            tot %= MOD;
            val = s[n / 2 + 1];
            sum += val * tot % MOD;
            sum %= MOD;
        }
        ans = (sum * 2 % MOD) * getpow(n * (n + 1) % MOD, MOD - 2) % MOD;
        ans %= MOD;
        cout << ans << endl;
    }
    return 0;
}
1002 Little Rabbit’s Equation

链接:HDU6828 Little Rabbit’s Equation

思路
  • 模拟
  • 注意 ascii 码中的 0 是字符串结束符
代码

(这个代码写的真的很屎)

#include 
using namespace std;
#define int long long
// const int MAXN = ;
// const int MOD = ;
// const int INF = ;
// const double eps = ;
// const int DIRX[] = {};
// const int DIRY[] = {};
string str;
char op;
string num[5];
int dci[5];

int32_t main(void)
{
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    while (cin >> str)
    {
        int cnt = 1;
        num[1] = "";
        num[2] = "";
        num[3] = "";
        for (int i = 0; i < str.length(); ++i)
        {
            if (str[i] == '=')
                cnt++;
            else if (str[i] == '+' || str[i] == '-' 
                    || str[i] == '*' || str[i] == '/')
            {
                cnt++;
                op = str[i];
            }
            else
            {
                if (str[i] >= '0' && str[i] <= '9')
                    num[cnt] += (char)(str[i] - '0' + 1);
                else
                    num[cnt] += (char)(str[i] - 'A' + 11);
            }
        }
        if (op == '-')
        {
            op = '+';
            swap(num[1], num[3]);
        }
        if (op == '/')
        {
            op = '*';
            swap(num[1], num[3]);
        }
        bool flg = false;
        for (int i = 2; i <= 16; ++i)
        {
            bool ok = false;
            for (int j = 1; j <= 3; ++j)
            {
                dci[j] = 0;
                int tmp = 1;
                for (int k = num[j].length() - 1; k >= 0; --k)
                {
                    if (num[j][k] - 1 >= i)
                    {
                        ok = true;
                        break;
                    }
                    dci[j] += (num[j][k] - 1) * tmp;
                    tmp *= i;
                }
                if (ok)
                    break;
            }
            if (ok)
                continue;
            if (!ok && op == '+')
            {
                if (dci[1] + dci[2] == dci[3])
                {
                    flg = true;
                    // cout << dci[1] << "+" << dci[2] << "=" << dci[3] << endl;
                    cout << i << endl;
                }
            }
            if (!ok && op == '*')
            {
                if (dci[1] * dci[2] == dci[3])
                {
                    flg = true;
                    // cout << dci[1] << "*" << dci[2] << "=" << dci[3] << endl;
                    cout << i << endl;
                }
            }
            if (flg)
                break;
        }
        if (!flg)
            cout << -1 << endl;
    }
    return 0;
}
1009 Divisibility

链接:HDU6835 Divisibility

思路
  • 同余,当且仅当 b ≡ 1   ( m o d   x ) b \equiv 1 \ (mod \ x) b1 (mod x) 时成立。
代码
#include 
using namespace std;
#define int long long
// const int MAXN = ;
// const int MOD = ;
// const int INF = ;
// const double eps = ;
// const int DIRX[] = {};
// const int DIRY[] = {};

int T;
int b, x;

int32_t main(void)
{
    int T;
    long long b, x;
    cin >> T;
    while (T--)
    {
        cin >> b >> x;
        if ((b - 1) % x == 0)
            cout << "T" << endl;
        else
            cout << "F" << endl;
    }
    
1006 A Very Easy Graph Problem

链接:HDU6832 A Very Easy Graph Problem

题意
  • 给定 n n n 个点的无向图,每个点拥有标号 1 1 1 0 0 0
  • m m m 条边,第 i i i 条边权为 2 i 2^i 2i
  • 计算每个标号为 1 1 1 的点到每个标号为 0 0 0 的点的最短路
思路
  • 并查集:由于第 i i i 条边权为 2 i 2^i 2i ,显然 2 i > ∑ k = 1 i − 1 2 k 2^i > \sum\limits_{k = 1}^{i - 1} 2^{k} 2i>k=1i12k,故若该条边对答案有贡献则该边起点与终点不连通

  • 最终图为一棵

  • D F S DFS DFS c n t [ n x t ] [ t y p ] cnt[nxt][typ] cnt[nxt][typ] 存储按 D F S DFS DFS 顺序访问,这个点之后所有的标号为 t y p typ typ 的点的个数

    • 根据 D F S DFS DFS 的性质,每条边、每个点只会被访问一次

    n o w → n x t now \to nxt nownxt 对答案的贡献为:

    • n x t nxt nxt 节点前所有 t y p = 0 typ = 0 typ=0 的点的个数 ∗ * n x t nxt nxt 节点后所有 t y p = 1 typ = 1 typ=1 的节点的个数
      • n x t nxt nxt 节点前所有 t y p = 0 typ = 0 typ=0 的点的个数 = = = 所有 t y p = 0 typ = 0 typ=0 的点的个数 − - n x t nxt nxt 节点后所有 t y p = 0 typ = 0 typ=0 的点的个数
    • n x t nxt nxt 节点前所有 t y p = 1 typ = 1 typ=1 的点的个数 ∗ * n x t nxt nxt 节点后所有 t y p = 0 typ = 0 typ=0 的节点的个数
代码
#include 
using namespace std;
#define int long long
const int MAXN = 1E5 + 7;
const int MAXM = 2E5 + 7;
const int MOD = 1E9 + 7;
// const int INF = ;
// const double eps = ;
// const int DIRX[] = {};
// const int DIRY[] = {};

int T;
int n, m;
int typ[MAXN];
int typ_0, typ_1;
int u, v;
vector<pair<int, int> > graph[MAXN];
int val;
int ans;

struct DSU
{
    int parent[MAXN];
    int n; // Num of Nodes
    int rank[MAXN]; // Rank of Node in Union

    void init_parent(int n)
    {
        this -> n = n;
        for (int i = 1; i <= n; ++i)
        {
            parent[i] = i;
            rank[i] = 0;
        }
    }

    int find_parent(int x)
    {
        if (parent[x] == x)
            return x;
        else
            parent[x] = find_parent(parent[x]);
        return parent[x];
    }

    bool check_unicom(int x, int y)
    {
        return find_parent(x) == find_parent(y);
    }

    void merge_node(int x, int y)
    {
        x = find_parent(x);
        y = find_parent(y);
        if (rank[x] > rank[y])
            parent[y] = x;
        else
        {
            parent[x] = y;
            if (rank[x] == rank[y])
                rank[y] += 1;
        }
    }
}dsu;

int cnt[MAXN][2];

void dfs(int now, int frm)
{
    cnt[now][typ[now]] = 1;
    for (int i = 0; i < graph[now].size(); ++i)
    {
        int nxt = graph[now][i].first;
        if (nxt == frm)
            continue;
        dfs(nxt, now);
        cnt[now][0] += cnt[nxt][0];
        cnt[now][1] += cnt[nxt][1];
    }
    for (int i = 0; i < graph[now].size(); ++i)
    {
        int nxt = graph[now][i].first;
        int val = graph[now][i].second;
        if (nxt == frm)
            continue;
        ans += (cnt[nxt][0] * (typ_1 - cnt[nxt][1]) % MOD) * val % MOD;
        ans %= MOD;
        ans += (cnt[nxt][1] * (typ_0 - cnt[nxt][0]) % MOD) * val % MOD;
        ans %= MOD;
    }
}

int32_t main(void)
{
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cin >> T;
    while (T--)
    {
        typ_0 = 0;
        typ_1 = 0;
        ans = 0;
        val = 1;
        cin >> n >> m;
        for (int i = 1; i <= n; ++i)
        {
            cnt[i][0] = cnt[i][1] = 0;
            graph[i].clear();
            cin >> typ[i];
            if (typ[i])
                typ_1++;
            else 
                typ_0++;
        }
        dsu.init_parent(n);
        for (int i = 1; i <= m; ++i)
        {
            val <<= 1;
            val %= MOD;
            cin >> u >> v;
            if (!dsu.check_unicom(u, v))
            {
                dsu.merge(u, v);
                graph[u].push_back({v, val});
                graph[v].push_back({u, val});
            }
        }
        dfs(1, -1);
        cout << ans << endl;
    }
    return 0;
}
1010 Expectation

链接:HDU6836 Expectation

题意
思路
代码
1005 Fragrant numbers

链接:HDU6831 Fragrant numbers

题意

(恶臭)

  • 字符串循环节 1145141919 1145141919 1145141919
  • 在任意位置插入 +   ∗   , + \ * \ , +  , ,构成的数字 n n n 所需最少的字符串长为多少
  • 若无法构成则输出 − 1 -1 1
思路
  • D F S DFS DFS 计算区间 [ l , r ] [l, r] [l,r] 中可能构成的数字有哪些
    • 递归求解 [ l , i ]   [ i + 1 , r ] [l, i] \ [i + 1, r] [l,i] [i+1,r]
    • 使用 s e t set set 存储

你可能感兴趣的:(acm竞赛)